diff --git a/src/Spring/Spring.Aop/Aspects/AbstractExceptionHandler.cs b/src/Spring/Spring.Aop/Aspects/AbstractExceptionHandler.cs
index 50382bc5..9eef2cea 100644
--- a/src/Spring/Spring.Aop/Aspects/AbstractExceptionHandler.cs
+++ b/src/Spring/Spring.Aop/Aspects/AbstractExceptionHandler.cs
@@ -79,7 +79,7 @@ namespace Spring.Aspects
/// Gets the source exception names.
///
/// The source exception names.
- public IList SourceExceptionNames
+ public virtual IList SourceExceptionNames
{
get { return sourceExceptionNames; }
set { sourceExceptionNames = value; }
@@ -89,7 +89,7 @@ namespace Spring.Aspects
/// Gets the source exception types.
///
/// The source exception types.
- public IList SourceExceptionTypes
+ public virtual IList SourceExceptionTypes
{
get { return sourceExceptionTypes; }
set { sourceExceptionTypes = value; }
@@ -99,7 +99,7 @@ namespace Spring.Aspects
/// Gets the action translation expression text
///
/// The action translation expression.
- public string ActionExpressionText
+ public virtual string ActionExpressionText
{
get { return actionExpressionText; }
set { actionExpressionText = value; }
diff --git a/src/Spring/Spring.Aop/Aspects/Exceptions/ExceptionHandlerAdvice.cs b/src/Spring/Spring.Aop/Aspects/Exceptions/ExceptionHandlerAdvice.cs
index 5d0cf6d6..3785a7ee 100644
--- a/src/Spring/Spring.Aop/Aspects/Exceptions/ExceptionHandlerAdvice.cs
+++ b/src/Spring/Spring.Aop/Aspects/Exceptions/ExceptionHandlerAdvice.cs
@@ -23,6 +23,9 @@ using System.Collections;
using System.Reflection;
using AopAlliance.Intercept;
using Common.Logging;
+using Spring.Context;
+using Spring.Objects.Factory.Config;
+using Spring.Util;
namespace Spring.Aspects.Exceptions
{
@@ -72,14 +75,19 @@ namespace Spring.Aspects.Exceptions
///
/// Log instance available to subclasses
///
- protected static readonly ILog log = LogManager.GetLogger(typeof(ExceptionHandlerAdvice));
+ protected static ILog log = LogManager.GetLogger(typeof(ExceptionHandlerAdvice));
private IList exceptionHandlers = new ArrayList();
- private string onExceptionNameRegex = @"^(on\s+exception\s+name)\s+(.*?)\s+(log|translate|wrap|replace|return|swallow)\s*(.*?)$";
+ ///
+ /// Holds shared handler definition templates
+ ///
+ private ExceptionHandlerTable exceptionHandlerTable = new ExceptionHandlerTable();
+
+ private string onExceptionNameRegex = @"^(on\s+exception\s+name)\s+(.*?)\s+(log|translate|wrap|replace|return|swallow|execute)\s*(.*?)$";
+
+ private string onExceptionRegex = @"^(on\s+exception\s+)(\(.*?\))\s+(log|translate|wrap|replace|return|swallow|execute)\s*(.*?)$";
- private string onExceptionRegex = @"^(on\s+exception\s+)(\(.*?\))\s+(log|translate|wrap|replace|return|swallow)\s*(.*?)$";
-
#endregion
#region Properties
@@ -114,6 +122,19 @@ namespace Spring.Aspects.Exceptions
set { exceptionHandlers = value; }
}
+
+ ///
+ /// Gets the exception handler dictionary. Allows for registration of a specific handler where the key
+ /// is the action type. This makes configuration of a custom exception handler easier, for example
+ /// LogExceptionHandler, in that only 'user friendly' properties such as LogName, etc., need to be configured
+ /// and not 'user unfriendly' properties such as ConstraintExpressionText and ActionExpressionText.
+ ///
+ /// The exception handler dictionary.
+ public ExceptionHandlerTable ExceptionHandlerDictionary
+ {
+ get { return exceptionHandlerTable; }
+ }
+
#endregion
#region IMethodInterceptor implementation
@@ -241,6 +262,7 @@ namespace Spring.Aspects.Exceptions
}
newExceptionHandlers.Add(handler);
}
+ //explicitly configured advice, must also configure ConstraintExpressionText and ActionExpressionText!
IExceptionHandler handlerObject = o as IExceptionHandler;
if (handlerObject != null)
{
@@ -315,42 +337,113 @@ namespace Spring.Aspects.Exceptions
{
if (parsedAdviceExpression.ActionText.IndexOf("log") >= 0)
{
- //TODO support user selection of level, log.Debug , log.Info etc.
- LogExceptionHandler handler = new LogExceptionHandler(parsedAdviceExpression.ExceptionNames);
+ IExceptionHandler handler;
+ if (exceptionHandlerTable.ContainsKey("log"))
+ {
+ handler = exceptionHandlerTable["log"];
+ AddExceptionNames(parsedAdviceExpression, handler);
+ } else
+ {
+ handler = CreateLogExceptionHandler(parsedAdviceExpression.ExceptionNames);
+ }
handler.ConstraintExpressionText = parsedAdviceExpression.ConstraintExpression;
- handler.ActionExpressionText = "#log.Trace(" + parsedAdviceExpression.ActionExpressionText + ")";
+ handler.ActionExpressionText = parsedAdviceExpression.ActionExpressionText;
return handler;
}
else if (parsedAdviceExpression.ActionText.IndexOf("translate") >= 0)
{
- TranslationExceptionHandler handler = new TranslationExceptionHandler(parsedAdviceExpression.ExceptionNames);
+ IExceptionHandler handler;
+ if (exceptionHandlerTable.Contains("translate"))
+ {
+ handler = exceptionHandlerTable["translate"];
+ AddExceptionNames(parsedAdviceExpression, handler);
+ }
+ else
+ {
+ handler = CreateTranslationExceptionHandler(parsedAdviceExpression.ExceptionNames);
+ }
handler.ConstraintExpressionText = parsedAdviceExpression.ConstraintExpression;
handler.ActionExpressionText = parsedAdviceExpression.ActionExpressionText;
return handler;
}
else if (parsedAdviceExpression.ActionText.IndexOf("wrap") >= 0)
{
- TranslationExceptionHandler handler = new TranslationExceptionHandler(parsedAdviceExpression.ExceptionNames);
+
+ IExceptionHandler handler;
+ if (exceptionHandlerTable.Contains("wrap"))
+ {
+ handler = exceptionHandlerTable["wrap"];
+ AddExceptionNames(parsedAdviceExpression, handler);
+ }
+ else
+ {
+ handler = CreateTranslationExceptionHandler(parsedAdviceExpression.ExceptionNames);
+ }
handler.ConstraintExpressionText = parsedAdviceExpression.ConstraintExpression;
- handler.ActionExpressionText = ParseWrappedExceptionExpression("wrap", parsedAdviceExpression.AdviceExpression);
+ handler.ActionExpressionText = ParseWrappedExceptionExpression("wrap", parsedAdviceExpression.AdviceExpression);
return handler;
}
else if (parsedAdviceExpression.ActionText.IndexOf("replace") >= 0)
{
- TranslationExceptionHandler handler = new TranslationExceptionHandler(parsedAdviceExpression.ExceptionNames);
+
+ IExceptionHandler handler;
+ if (exceptionHandlerTable.Contains("replace"))
+ {
+ handler = exceptionHandlerTable["replace"];
+ AddExceptionNames(parsedAdviceExpression, handler);
+ } else
+ {
+ handler = CreateTranslationExceptionHandler(parsedAdviceExpression.ExceptionNames);
+ }
handler.ConstraintExpressionText = parsedAdviceExpression.ConstraintExpression;
handler.ActionExpressionText = ParseWrappedExceptionExpression("replace", parsedAdviceExpression.AdviceExpression);
return handler;
}
else if (parsedAdviceExpression.ActionText.IndexOf("swallow") >= 0)
{
- SwallowExceptionHandler handler = new SwallowExceptionHandler(parsedAdviceExpression.ExceptionNames);
+
+ IExceptionHandler handler;
+ if (exceptionHandlerTable.Contains("swallow"))
+ {
+ handler = exceptionHandlerTable["swallow"];
+ AddExceptionNames(parsedAdviceExpression, handler);
+ }
+ else
+ {
+ handler = CreateSwallowExceptionHander(parsedAdviceExpression);
+ }
handler.ConstraintExpressionText = parsedAdviceExpression.ConstraintExpression;
return handler;
}
else if (parsedAdviceExpression.ActionText.IndexOf("return") >= 0)
{
- ReturnValueExceptionHandler handler = new ReturnValueExceptionHandler(parsedAdviceExpression.ExceptionNames);
+
+ IExceptionHandler handler;
+ if (exceptionHandlerTable.Contains("return"))
+ {
+ handler = exceptionHandlerTable["return"];
+ AddExceptionNames(parsedAdviceExpression, handler);
+ }
+ else
+ {
+ handler = CreateReturnValueExceptionHandler(parsedAdviceExpression);
+ }
+ handler.ConstraintExpressionText = parsedAdviceExpression.ConstraintExpression;
+ handler.ActionExpressionText = parsedAdviceExpression.ActionExpressionText;
+ return handler;
+ }
+ else if (parsedAdviceExpression.ActionText.IndexOf("execute") >= 0)
+ {
+ IExceptionHandler handler;
+ if (exceptionHandlerTable.Contains("execute"))
+ {
+ handler = exceptionHandlerTable["execute"];
+ AddExceptionNames(parsedAdviceExpression, handler);
+ }
+ else
+ {
+ handler = CreateExecuteSpelExceptionHandler(parsedAdviceExpression);
+ }
handler.ConstraintExpressionText = parsedAdviceExpression.ConstraintExpression;
handler.ActionExpressionText = parsedAdviceExpression.ActionExpressionText;
return handler;
@@ -362,6 +455,62 @@ namespace Spring.Aspects.Exceptions
return null;
}
+ ///
+ /// Creates the execute spel exception handler.
+ ///
+ /// The parsed advice expression.
+ ///
+ protected virtual IExceptionHandler CreateExecuteSpelExceptionHandler(ParsedAdviceExpression parsedAdviceExpression)
+ {
+ IExceptionHandler handler;
+ handler = new ExecuteSpelExceptionHandler(parsedAdviceExpression.ExceptionNames);
+ return handler;
+ }
+
+ ///
+ /// Creates the return value exception handler.
+ ///
+ /// The parsed advice expression.
+ ///
+ protected virtual IExceptionHandler CreateReturnValueExceptionHandler(ParsedAdviceExpression parsedAdviceExpression)
+ {
+ IExceptionHandler handler;
+ handler = new ReturnValueExceptionHandler(parsedAdviceExpression.ExceptionNames);
+ return handler;
+ }
+
+ ///
+ /// Creates the swallow exception hander.
+ ///
+ /// The parsed advice expression.
+ ///
+ protected virtual IExceptionHandler CreateSwallowExceptionHander(ParsedAdviceExpression parsedAdviceExpression)
+ {
+ IExceptionHandler handler;
+ handler = new SwallowExceptionHandler(parsedAdviceExpression.ExceptionNames);
+ return handler;
+ }
+
+ ///
+ /// Creates the translation exception handler.
+ ///
+ /// The exception names.
+ ///
+ protected virtual IExceptionHandler CreateTranslationExceptionHandler(string[] exceptionNames)
+ {
+ return new TranslationExceptionHandler(exceptionNames);
+ }
+
+ ///
+ /// Creates the log exception handler.
+ ///
+ /// The exception names.
+ /// Log exception
+ protected virtual LogExceptionHandler CreateLogExceptionHandler(string[] exceptionNames)
+ {
+ return new LogExceptionHandler(exceptionNames);
+ }
+
///
/// Parses the wrapped exception expression.
///
@@ -404,7 +553,83 @@ namespace Spring.Aspects.Exceptions
}
+ private void AddExceptionNames(ParsedAdviceExpression parsedAdviceExpression, IExceptionHandler handler)
+ {
+ foreach (string exceptionName in parsedAdviceExpression.ExceptionNames)
+ {
+ handler.SourceExceptionNames.Add(exceptionName);
+ }
+ }
+
+ #endregion
+
+ #region ExceptionHandlerTable class
+
+ ///
+ /// A specialized dictionary for key value pairs of (string, IExceptionHandler)
+ ///
+ public class ExceptionHandlerTable : Hashtable
+ {
+ ///
+ /// Adds the specified key.
+ ///
+ /// The key.
+ /// The value.
+ public void Add(string key, IExceptionHandler value)
+ {
+ lock (SyncRoot)
+ {
+ base[key] = value;
+ }
+ }
+
+ ///
+ /// Gets the with the specified key.
+ ///
+ ///
+ public IExceptionHandler this[string key]
+ {
+ get
+ {
+ lock (SyncRoot)
+ {
+ return (IExceptionHandler)base[key];
+ }
+ }
+ }
+
+ ///
+ /// Adds an element with the specified key and value into the .
+ ///
+ /// The key of the element to add.
+ /// The value of the element to add. The value can be null.
+ ///
+ /// is null.
+ /// An element with the same key already exists in the .
+ /// or key is not a string or value is not an IExceptionHandler.
+ /// The is read-only.-or- The has a fixed size.
+ public override void Add(object key, object value)
+ {
+ AssertUtils.AssertArgumentType(key, "key", typeof(string), "Key must be a string");
+ AssertUtils.AssertArgumentType(value, "value", typeof(IExceptionHandler), "Key must be a IExceptionHandler");
+ this.Add((string)key, (IExceptionHandler)value);
+ }
+
+ ///
+ /// Gets the with the specified key.
+ ///
+ ///
+ public override object this[object key]
+ {
+ get
+ {
+ return this[(string)key];
+ }
+ }
+ }
#endregion
}
+
+
}
\ No newline at end of file
diff --git a/src/Spring/Spring.Aop/Aspects/Exceptions/ExecuteSpelExceptionHandler.cs b/src/Spring/Spring.Aop/Aspects/Exceptions/ExecuteSpelExceptionHandler.cs
new file mode 100644
index 00000000..4204fc64
--- /dev/null
+++ b/src/Spring/Spring.Aop/Aspects/Exceptions/ExecuteSpelExceptionHandler.cs
@@ -0,0 +1,48 @@
+
+
+using System;
+using System.Collections;
+using Spring.Expressions;
+
+namespace Spring.Aspects.Exceptions
+{
+ ///
+ /// Executes an abribtrary Spring Expression Language (SpEL) expression as an action when handling an exception.
+ ///
+ public class ExecuteSpelExceptionHandler : AbstractExceptionHandler
+ {
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ public ExecuteSpelExceptionHandler()
+ {
+ }
+
+ ///
+ /// Initializes a new instance of the class.
+ ///
+ /// The exception names.
+ public ExecuteSpelExceptionHandler(string[] exceptionNames)
+ : base(exceptionNames)
+ {
+ }
+
+ ///
+ /// Handles the exception.
+ ///
+ /// The return value from handling the exception, if not rethrown or a new exception is thrown.
+ public override object HandleException(IDictionary callContextDictionary)
+ {
+ try
+ {
+ IExpression expression = Expression.Parse(ActionExpressionText);
+ expression.GetValue(null, callContextDictionary);
+ }
+ catch (Exception e)
+ {
+ log.Warn("Was not able to evaluate action expression [" + ActionExpressionText + "]", e);
+ }
+ return null;
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Spring/Spring.Aop/Aspects/Exceptions/LogExceptionHandler.cs b/src/Spring/Spring.Aop/Aspects/Exceptions/LogExceptionHandler.cs
index f4cd6492..f550fa00 100644
--- a/src/Spring/Spring.Aop/Aspects/Exceptions/LogExceptionHandler.cs
+++ b/src/Spring/Spring.Aop/Aspects/Exceptions/LogExceptionHandler.cs
@@ -37,6 +37,11 @@ namespace Spring.Aspects.Exceptions
private LogLevel logLevel = LogLevel.Trace;
private bool logMessageOnly = false;
+
+ private bool first = true;
+
+ private string actionExpressionText;
+
#endregion
@@ -91,6 +96,35 @@ namespace Spring.Aspects.Exceptions
set { logMessageOnly = value; }
}
+
+ ///
+ /// Gets the action translation expression text. Overridden to add approprate settings to
+ /// the SpEL expression that does the logging so that it depends on the values of LogLevel and
+ /// LogMessageOnly. Those properties must be set to the desired values before calling this method.
+ ///
+ ///
+ /// The action translation expression.
+ public override string ActionExpressionText
+ {
+ get { return actionExpressionText; }
+ set
+ {
+ if (first)
+ {
+ first = false;
+ string textPart1 = "#log." + LogLevel.ToString() + "(" + value;
+ if (logMessageOnly)
+ {
+ actionExpressionText = textPart1 + ")";
+ }
+ else
+ {
+ actionExpressionText = textPart1 + ", #e)";
+ }
+ }
+ }
+ }
+
///
/// Handles the exception.
///
@@ -100,8 +134,9 @@ namespace Spring.Aspects.Exceptions
///
public override object HandleException(IDictionary callContextDictionary)
{
- ILog log = LogManager.GetLogger(logName);
- callContextDictionary.Add("log", log);
+ //TODO log name is targettype.
+ ILog adviceLogger = LogManager.GetLogger(logName);
+ callContextDictionary.Add("log", adviceLogger);
try
{
IExpression expression = Expression.Parse(ActionExpressionText);
@@ -113,5 +148,6 @@ namespace Spring.Aspects.Exceptions
}
return "logged";
}
+
}
}
\ No newline at end of file
diff --git a/src/Spring/Spring.Aop/Spring.Aop.2008.csproj b/src/Spring/Spring.Aop/Spring.Aop.2008.csproj
index be7de0b1..224a1ce9 100644
--- a/src/Spring/Spring.Aop/Spring.Aop.2008.csproj
+++ b/src/Spring/Spring.Aop/Spring.Aop.2008.csproj
@@ -410,6 +410,7 @@
+
diff --git a/test/Spring/Spring.Aop.Tests/Aspects/Exception/CaptureOutputLogger.cs b/test/Spring/Spring.Aop.Tests/Aspects/Exception/CaptureOutputLogger.cs
new file mode 100644
index 00000000..724afaa1
--- /dev/null
+++ b/test/Spring/Spring.Aop.Tests/Aspects/Exception/CaptureOutputLogger.cs
@@ -0,0 +1,210 @@
+
+
+using System;
+using System.Collections;
+using System.Globalization;
+using System.Text;
+using Common.Logging;
+
+namespace Spring.Aspects.Exceptions
+{
+ public class CaptureOutputLogger : ILog
+ {
+
+ private LogLevel _currentLogLevel = LogLevel.All;
+
+ private IList logMessages = new ArrayList();
+
+
+ public IList LogMessages
+ {
+ get { return logMessages; }
+ set { logMessages = value; }
+ }
+
+ ///
+ /// Do the actual logging by constructing the log message using a then
+ /// sending the output to .
+ ///
+ /// The of the message.
+ /// The log message.
+ /// An optional associated with the message.
+ private void Write(LogLevel level, object message, Exception e)
+ {
+ // Use a StringBuilder for better performance
+ StringBuilder sb = new StringBuilder();
+ // Append date-time if so configured
+ // Append a readable representation of the log level
+ sb.Append(("[" + level.ToString().ToUpper() + "]").PadRight(8));
+
+ // Append the message
+ sb.Append(message);
+
+ // Append stack trace if not null
+ if (e != null)
+ {
+ sb.Append(Environment.NewLine).Append(e.ToString());
+ }
+
+ // Print to the appropriate destination
+ logMessages.Add(sb.ToString());
+ }
+
+ ///
+ /// Determines if the given log level is currently enabled.
+ ///
+ ///
+ ///
+ private bool IsLevelEnabled(LogLevel level)
+ {
+ int iLevel = (int)level;
+ int iCurrentLogLevel = (int)_currentLogLevel;
+
+ // return iLevel.CompareTo(iCurrentLogLevel); better ???
+ return (iLevel >= iCurrentLogLevel);
+ }
+
+ #region ILog Members
+
+ public void Trace(object message)
+ {
+ Trace(message, null);
+ }
+
+ public void Trace(object message, Exception e)
+ {
+ if (IsLevelEnabled(LogLevel.Trace))
+ {
+ Write(LogLevel.Trace, message, e);
+ }
+ }
+
+ public void Debug(object message)
+ {
+ Debug(message, null);
+ }
+
+ public void Debug(object message, Exception e)
+ {
+ if (IsLevelEnabled(LogLevel.Debug))
+ {
+ Write(LogLevel.Debug, message, e);
+ }
+ }
+
+ public void Error(object message)
+ {
+ Error(message, null);
+ }
+
+ public void Error(object message, Exception e)
+ {
+ if (IsLevelEnabled(LogLevel.Error))
+ {
+ Write(LogLevel.Error, message, e);
+ }
+ }
+
+ public void Fatal(object message)
+ {
+ Fatal(message, null);
+ }
+
+ public void Fatal(object message, Exception e)
+ {
+ if (IsLevelEnabled(LogLevel.Fatal))
+ {
+ Write(LogLevel.Fatal, message, e);
+ }
+ }
+
+ public void Info(object message)
+ {
+ Info(message, null);
+ }
+
+ public void Info(object message, Exception e)
+ {
+ if (IsLevelEnabled(LogLevel.Info))
+ {
+ Write(LogLevel.Info, message, e);
+ }
+ }
+
+ public void Warn(object message)
+ {
+ Warn(message, null);
+ }
+
+ public void Warn(object message, Exception e)
+ {
+ if (IsLevelEnabled(LogLevel.Warn))
+ {
+ Write(LogLevel.Warn, message, e);
+ }
+ }
+
+ ///
+ /// Returns if the current is greater than or
+ /// equal to . If it is, all messages will be sent to .
+ ///
+ public bool IsTraceEnabled
+ {
+ get { return IsLevelEnabled(LogLevel.Trace); }
+ }
+
+ ///
+ /// Returns if the current is greater than or
+ /// equal to . If it is, all messages will be sent to .
+ ///
+ public bool IsDebugEnabled
+ {
+ get { return IsLevelEnabled(LogLevel.Debug); }
+ }
+
+ ///
+ /// Returns if the current is greater than or
+ /// equal to . If it is, only messages with a of
+ /// and will be sent to .
+ ///
+ public bool IsErrorEnabled
+ {
+ get { return IsLevelEnabled(LogLevel.Error); }
+ }
+
+ ///
+ /// Returns if the current is greater than or
+ /// equal to . If it is, only messages with a of
+ /// will be sent to .
+ ///
+ public bool IsFatalEnabled
+ {
+ get { return IsLevelEnabled(LogLevel.Fatal); }
+ }
+
+ ///
+ /// Returns if the current is greater than or
+ /// equal to . If it is, only messages with a of
+ /// , , , and
+ /// will be sent to .
+ ///
+ public bool IsInfoEnabled
+ {
+ get { return IsLevelEnabled(LogLevel.Info); }
+ }
+
+
+ ///
+ /// Returns if the current is greater than or
+ /// equal to . If it is, only messages with a of
+ /// , , and
+ /// will be sent to .
+ ///
+ public bool IsWarnEnabled
+ {
+ get { return IsLevelEnabled(LogLevel.Warn); }
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/test/Spring/Spring.Aop.Tests/Aspects/Exception/CaptureOutputLoggerFactoryAdapter.cs b/test/Spring/Spring.Aop.Tests/Aspects/Exception/CaptureOutputLoggerFactoryAdapter.cs
new file mode 100644
index 00000000..d6bd5993
--- /dev/null
+++ b/test/Spring/Spring.Aop.Tests/Aspects/Exception/CaptureOutputLoggerFactoryAdapter.cs
@@ -0,0 +1,47 @@
+
+
+using System;
+using System.Collections.Specialized;
+using Common.Logging;
+
+namespace Spring.Aspects.Exceptions
+{
+ public class CaptureOutputLoggerFactoryAdapter : ILoggerFactoryAdapter
+ {
+ private CaptureOutputLogger adviceLogger;
+
+ public CaptureOutputLoggerFactoryAdapter()
+ {
+ }
+
+ public CaptureOutputLoggerFactoryAdapter(NameValueCollection properties)
+ {
+ }
+
+
+ public CaptureOutputLogger AdviceLogger
+ {
+ get { return adviceLogger; }
+ }
+
+ #region ILoggerFactoryAdapter Members
+
+ public ILog GetLogger(Type type)
+ {
+ return GetLogger(type.FullName);
+ }
+
+ public ILog GetLogger(string name)
+ {
+ CaptureOutputLogger logger = new CaptureOutputLogger();
+ if (name.Equals("adviceHandler") || name.IndexOf("LogExceptionHandler") >= 0)
+ {
+ adviceLogger = logger;
+ }
+
+ return logger;
+ }
+
+ #endregion
+ }
+}
\ No newline at end of file
diff --git a/test/Spring/Spring.Aop.Tests/Aspects/Exception/ExceptionHandlerAspectIntegrationTests.cs b/test/Spring/Spring.Aop.Tests/Aspects/Exception/ExceptionHandlerAspectIntegrationTests.cs
index d6e89750..b7bf57d6 100644
--- a/test/Spring/Spring.Aop.Tests/Aspects/Exception/ExceptionHandlerAspectIntegrationTests.cs
+++ b/test/Spring/Spring.Aop.Tests/Aspects/Exception/ExceptionHandlerAspectIntegrationTests.cs
@@ -30,6 +30,7 @@ using Spring.Aop.Framework;
using Spring.Aspects.Exceptions;
using Spring.Expressions;
using Spring.Objects;
+using Spring.Util;
#endregion
@@ -43,24 +44,64 @@ namespace Spring.Aspects.Exceptions
public class ExceptionHandlerAspectIntegrationTests
{
private ExceptionHandlerAdvice exceptionHandlerAdvice;
-
+ private CaptureOutputLoggerFactoryAdapter loggerFactoryAdapter;
+ private ILoggerFactoryAdapter originalAdapter;
+ private static bool spelActionExecuted = false;
[SetUp]
public void Setup()
{
- LogManager.Adapter = new ConsoleOutLoggerFactoryAdapter(new NameValueCollection());
- exceptionHandlerAdvice = new ExceptionHandlerAdvice();
+ originalAdapter = LogManager.Adapter;
+ loggerFactoryAdapter = new CaptureOutputLoggerFactoryAdapter();
+ LogManager.Adapter = loggerFactoryAdapter;
+ exceptionHandlerAdvice = new ExceptionHandlerAdvice();
+ }
+
+ public void TearDown()
+ {
+ loggerFactoryAdapter.AdviceLogger.LogMessages.Clear();
+
+ //reset so other tests can produce some output if needed.
+ LogManager.Adapter = originalAdapter;
+ }
+
+ [Test]
+ public void ExecuteSpelAction()
+ {
+ string executeHandlerText =
+ "on exception name ArithmeticException execute Spring.Aspects.Exceptions.ExceptionHandlerAspectIntegrationTests.Executed(true)";
+ ITestObject to = CreateTestObjectProxy(executeHandlerText);
+
+ try
+ {
+ to.Exceptional(new ArithmeticException());
+ }
+ catch (ArithmeticException)
+ {
+ Assert.IsTrue(spelActionExecuted);
+ }
+ }
+
+ public static void Executed(bool val)
+ {
+ spelActionExecuted = val;
}
[Test]
public void LoggingTest()
{
+ CaptureOutputLoggerFactoryAdapter loggerFactoryAdapter = new CaptureOutputLoggerFactoryAdapter();
+ LogManager.Adapter = loggerFactoryAdapter;
+
LogExceptionHandler logHandler = new LogExceptionHandler();
- string testText = @"#log.Debug('Hello World, exception message = ' + #e.Message + ', target method = ' + #method.Name)";
+ logHandler.LogName = "adviceHandler";
+ string testText = @"'Hello World, exception message = ' + #e.Message + ', target method = ' + #method.Name";
logHandler.SourceExceptionNames.Add("ArithmeticException");
logHandler.ActionExpressionText = testText;
exceptionHandlerAdvice.ExceptionHandlers.Add(logHandler);
+ exceptionHandlerAdvice.AfterPropertiesSet();
+
ProxyFactory pf = new ProxyFactory(new TestObject());
pf.AddAdvice(exceptionHandlerAdvice);
ITestObject to = (ITestObject) pf.GetProxy();
@@ -71,7 +112,17 @@ namespace Spring.Aspects.Exceptions
Assert.Fail("Should have thrown exception when only logging");
} catch (ArithmeticException)
{
- //TODO need to create adapter implementation to replay logged text.
+
+
+ bool found = false;
+ foreach (string message in loggerFactoryAdapter.AdviceLogger.LogMessages)
+ {
+ if (message.IndexOf("Hello World") >= 0)
+ {
+ found = true;
+ }
+ }
+ Assert.IsTrue(found, "did not find logging output");
}
}
@@ -81,7 +132,15 @@ namespace Spring.Aspects.Exceptions
{
string logHandlerText = "on exception name ArithmeticException log 'My Message, Method Name ' + #method.Name";
- ExecuteLoggingHandler(logHandlerText);
+ ExecuteLoggingHandler(logHandlerText, "My Message");
+ }
+
+ [Test]
+ public void LoggingTestWithStringExplicitHandler()
+ {
+ string logHandlerText = "on exception name ArithmeticException log 'My Message, Method Name ' + #method.Name";
+
+ ExecuteLoggingHandler(logHandlerText, "My Message");
}
[Test]
@@ -89,18 +148,26 @@ namespace Spring.Aspects.Exceptions
{
string logHandlerText = "on exception (#e is T(System.ArithmeticException)) log 'My Message, Method Name ' + #method.Name";
- ExecuteLoggingHandler(logHandlerText);
+ ExecuteLoggingHandler(logHandlerText, "My Message");
}
[Test]
- public void LoggingTestWithConstraintExpressionWithExceptionHandler()
+ public void LoggingTestWithConstraintExpressionWithExceptionHandlerInList()
{
LogExceptionHandler exHandler = new LogExceptionHandler();
exHandler.ConstraintExpressionText = "#e is T(System.ArithmeticException)";
- exHandler.LogName = "Cms.Session.ExceptionHandler";
+ exHandler.LogName = "adviceHandler";
exHandler.ActionExpressionText = "#log.Fatal('Request Timeout occured', #e)";
- ExecuteLoggingHandler(exHandler);
+ ExecuteLoggingHandlerInList(exHandler, "Request Timeout");
+ }
+
+ [Test]
+ public void LoggingTestWithConstraintExpressionWithKeyedExceptionHandler()
+ {
+ LogExceptionHandler exHandler = new LogExceptionHandler();
+ ExecuteLoggingHandlerWithKeyedLogHandler(exHandler,
+ @"on exception (#e is T(System.ArithmeticException)) log 'Request Timeout occured'", "Request Timeout");
}
[Test]
@@ -109,7 +176,7 @@ namespace Spring.Aspects.Exceptions
{
string logHandlerText = "on foobar name ArithmeticException log 'My Message, Method Name ' + #method.Name";
- ExecuteLoggingHandler(logHandlerText);
+ ExecuteLoggingHandler(logHandlerText, "My Message");
}
[Test]
@@ -117,11 +184,8 @@ namespace Spring.Aspects.Exceptions
{
string logHandlerText = "on exception (#e is System.FooBar) log 'My Message, Method Name ' + #method.Name";
- ExecuteLoggingHandler(logHandlerText);
-
- //No exception is expected.
+ ExecuteLoggingHandler(logHandlerText, "[WARN] Was not able to evaluate constraint expression [#e is System.FooBar]");
- //TODO need to make sure log statement was executed.
}
[Test]
@@ -129,14 +193,11 @@ namespace Spring.Aspects.Exceptions
{
string logHandlerText = "on exception (1+1) log 'My Message, Method Name ' + #method.Name";
- ExecuteLoggingHandler(logHandlerText);
+ ExecuteLoggingHandler(logHandlerText, "[WARN] Was not able to unbox constraint expression to boolean [1+1]");
- //No exception is expected.
-
- //TODO need to make sure log statement was executed.
}
- private void ExecuteLoggingHandler(string logHandlerText)
+ private void ExecuteLoggingHandler(string logHandlerText, string searchString)
{
ITestObject to = CreateTestObjectProxy(logHandlerText);
@@ -146,13 +207,13 @@ namespace Spring.Aspects.Exceptions
}
catch (ArithmeticException)
{
- //TODO assert logging occured.
+ AssertSearchString(searchString);
}
}
- private void ExecuteLoggingHandler(IExceptionHandler handler)
+ private void ExecuteLoggingHandlerInList(IExceptionHandler handler, string searchString)
{
- ITestObject to = CreateTestObjectProxy(handler);
+ ITestObject to = CreateTestObjectProxyInList(handler);
try
{
@@ -160,11 +221,23 @@ namespace Spring.Aspects.Exceptions
}
catch (ArithmeticException)
{
- //TODO assert logging occured.
+ AssertSearchString(searchString);
}
}
+ private void ExecuteLoggingHandlerWithKeyedLogHandler(IExceptionHandler handler, string handlerText, string searchString)
+ {
+ ITestObject to = CreateTestObjectProxyWithKeyedHandler(handler, handlerText);
+ try
+ {
+ to.Exceptional(new ArithmeticException());
+ }
+ catch (ArithmeticException)
+ {
+ AssertSearchString(searchString);
+ }
+ }
[Test]
public void TranslationWithString()
@@ -390,6 +463,19 @@ namespace Spring.Aspects.Exceptions
return CreateProxy();
}
+ private ITestObject CreateTestObjectProxyInList(IExceptionHandler exceptionHander)
+ {
+ exceptionHandlerAdvice.ExceptionHandlers.Add(exceptionHander);
+ return CreateProxy();
+ }
+
+ private ITestObject CreateTestObjectProxyWithKeyedHandler(IExceptionHandler exceptionHander, string handlerText)
+ {
+ exceptionHandlerAdvice.ExceptionHandlerDictionary.Add("log", exceptionHander);
+ exceptionHandlerAdvice.ExceptionHandlers.Add(handlerText);
+ return CreateProxy();
+ }
+
private ITestObject CreateProxy()
{
exceptionHandlerAdvice.AfterPropertiesSet();
@@ -397,6 +483,19 @@ namespace Spring.Aspects.Exceptions
pf.AddAdvice(exceptionHandlerAdvice);
return (ITestObject)pf.GetProxy();
}
-
+
+ private void AssertSearchString(string searchString)
+ {
+ bool found = false;
+ foreach (string message in loggerFactoryAdapter.AdviceLogger.LogMessages)
+ {
+ if (message.IndexOf(searchString) >= 0)
+ {
+ found = true;
+ }
+ }
+ Assert.IsTrue(found, "did not find logging output [" + searchString + "] Logging values = "
+ + StringUtils.CollectionToCommaDelimitedString(loggerFactoryAdapter.AdviceLogger.LogMessages));
+ }
}
}
\ No newline at end of file
diff --git a/test/Spring/Spring.Aop.Tests/Spring.Aop.Tests.2008.csproj b/test/Spring/Spring.Aop.Tests/Spring.Aop.Tests.2008.csproj
index 409b6c12..939054a5 100644
--- a/test/Spring/Spring.Aop.Tests/Spring.Aop.Tests.2008.csproj
+++ b/test/Spring/Spring.Aop.Tests/Spring.Aop.Tests.2008.csproj
@@ -251,6 +251,8 @@
+
+
diff --git a/test/Spring/Spring.Aop.Tests/Spring.Aop.Tests.dll.config b/test/Spring/Spring.Aop.Tests/Spring.Aop.Tests.dll.config
index 7aec1f96..62a67b4a 100644
--- a/test/Spring/Spring.Aop.Tests/Spring.Aop.Tests.dll.config
+++ b/test/Spring/Spring.Aop.Tests/Spring.Aop.Tests.dll.config
@@ -23,8 +23,15 @@ limitations under the License.
+
-
+
+
\ No newline at end of file