From e842673936f5e415c8449ffe310514501e5c0101 Mon Sep 17 00:00:00 2001 From: markpollack Date: Thu, 30 Jul 2009 03:32:45 +0000 Subject: [PATCH] SPRNET-1081 - Add an ExceptionThrowingAction to Spring.Validation framework --- doc/reference/src/validation.xml | 18 +- .../Target/AbstractPrototypeTargetSource.cs | 478 +++++++++--------- .../Spring.Core/Spring.Core.2008.csproj | 4 +- .../Validation/Actions/ExceptionAction.cs | 97 ++++ .../Config/ValidationNamespaceParser.cs | 31 +- .../Config/spring-validation-1.1.xsd | 276 +++------- .../Config/spring-validation-1.3.xsd | 294 +++++++++++ .../Spring.Core.Tests/Objects/TestObject.cs | 6 +- .../Spring.Core.Tests.2008.csproj | 4 +- .../Actions/ExceptionActionTests.cs | 109 ++++ .../ValidationNamespaceParserTests.cs | 23 +- ...spaceParserTests_WhenConfigFileIsValid.xml | 7 +- 12 files changed, 900 insertions(+), 447 deletions(-) create mode 100644 src/Spring/Spring.Core/Validation/Actions/ExceptionAction.cs create mode 100644 src/Spring/Spring.Core/Validation/Config/spring-validation-1.3.xsd create mode 100644 test/Spring/Spring.Core.Tests/Validation/Actions/ExceptionActionTests.cs diff --git a/doc/reference/src/validation.xml b/doc/reference/src/validation.xml index 5dfeac31..61dad4d2 100644 --- a/doc/reference/src/validation.xml +++ b/doc/reference/src/validation.xml @@ -565,6 +565,22 @@ +
+ Exception Action + + If you would like an exception to be thrown when validation fails + use the exception action. + + <v:exception/> + + This will throw an exception of the type ValidationException and + you can access error information via its ValidationErrors property. To + throw your own custom exception, provide a SpEL fragment that + instantiates the custom exception. + + <v:exception throw='new System.InvalidOperationException("invalid")'/> +
+
Generic Actions @@ -888,7 +904,7 @@ bool userInfoIsValid = userInfoValidator.Validate(userInfo, errors);
How Validate() and Validation Controls play together - Validation Controls (ValidationSummary, ValidationError) need to + Validation Controls (ValidationSummary, ValidationError) need to somehow get the list of errors collected during validation. Both, Spring.Web.UI.Page and Spring.Web.UI.UserControl come with a ValidationErrors property and implement IValidationContainer. diff --git a/src/Spring/Spring.Aop/Aop/Target/AbstractPrototypeTargetSource.cs b/src/Spring/Spring.Aop/Aop/Target/AbstractPrototypeTargetSource.cs index 3ea9496f..fd3234bc 100644 --- a/src/Spring/Spring.Aop/Aop/Target/AbstractPrototypeTargetSource.cs +++ b/src/Spring/Spring.Aop/Aop/Target/AbstractPrototypeTargetSource.cs @@ -1,226 +1,226 @@ -#region License - -/* - * Copyright © 2002-2005 the original author or authors. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#endregion - -#region Imports - -using System; -using System.Globalization; -using Common.Logging; -using Spring.Objects.Factory; -using Spring.Objects.Factory.Support; -using Spring.Util; - -#endregion - -namespace Spring.Aop.Target -{ - /// - /// Base class for dynamic - /// implementations that can create new prototype object instances to - /// support a pooling or new-instance-per-invocation strategy. - /// - /// - ///

- /// All such s must run in an - /// , as they need to - /// call the - /// method to create a new prototype instance. - ///

- ///
- /// Rod Johnson - /// Federico Spinazzi (.NET) - public abstract class AbstractPrototypeTargetSource - : ITargetSource, IObjectFactoryAware, IInitializingObject - { - #region Constructor (s) / Destructor - - /// - /// Creates a new instance of the - /// - /// class. - /// - /// - ///

- /// This is an class, and as such exposes no - /// public constructors. - ///

- ///
- protected AbstractPrototypeTargetSource() - { - } - - #endregion - - #region Properties - - /// - /// The name of the target object to be created on each invocation. - /// - /// - ///

- /// This object should be a prototype, or the same instance will always - /// be obtained from the owning . - ///

- ///
- public virtual string TargetObjectName - { - get { return _targetObjectName; } - set { - _targetObjectName = value; - } - } - - /// - /// The of the target object. - /// - public virtual Type TargetType - { - get { return _targetType; } - } - - /// - /// Is the target source static? - /// - /// - /// if the target source is static. - /// - public virtual bool IsStatic - { - get { return false; } - } - - /// - /// The target factory that will be used to perform the lookup - /// of the object referred to by the - /// property. - /// - /// - ///

- /// Needed so that prototype instances can be created as necessary. - ///

- ///
- /// - /// The owning - /// (will never be ). - /// - /// - /// In case of initialization errors. - /// - /// - public virtual IObjectFactory ObjectFactory - { - get { return _owningObjectFactory; } - set - { - _owningObjectFactory = value; - if (!value.IsPrototype(TargetObjectName)) - { - throw new ObjectDefinitionStoreException( - "Cannot use PrototypeTargetSource against a " + - "Singleton object; instances would not be independent."); - } - - #region Instrumentation - - if (logger.IsDebugEnabled) - { - logger.Debug(string.Format( - "Getting object with name '{0}' to determine class.", - TargetObjectName)); - } - - #endregion - - _targetType = _owningObjectFactory.GetType(TargetObjectName); - } - } - - #endregion - - #region Methods - - /// - /// Subclasses should use this method to create a new prototype instance. - /// - protected virtual object NewPrototypeInstance() - { - #region Instrumentation - - if (logger.IsDebugEnabled) - { - logger.Debug(string.Format( - "Creating new target from object '{0}'.", - TargetObjectName)); - } - - #endregion - - return ObjectFactory.GetObject(TargetObjectName); - } - - /// - /// Returns the target object. - /// - /// The target object. - /// - /// If unable to obtain the target object. - /// - public abstract object GetTarget(); - - /// - /// Releases the target object. - /// - /// The target object to release. - public virtual void ReleaseTarget(object target) - { - } - - /// - /// Invoked by an - /// after it has set all object properties supplied - /// (and satisfied the - /// - /// and - /// interfaces). - /// - /// - ///

- /// Ensures that the property has been - /// set to a valid value (i.e. is not or a string - /// that consists solely of whitespace). - ///

- ///
- /// - /// In the event of misconfiguration (such as failure to set an essential - /// property) or if initialization fails. - /// - /// - public virtual void AfterPropertiesSet() - { - AssertUtils.ArgumentHasText( - TargetObjectName, "TargetObjectName", - "The 'TargetObjectName' property must have a value."); - } - - #endregion - +#region License + +/* + * Copyright © 2002-2005 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#endregion + +#region Imports + +using System; +using System.Globalization; +using Common.Logging; +using Spring.Objects.Factory; +using Spring.Objects.Factory.Support; +using Spring.Util; + +#endregion + +namespace Spring.Aop.Target +{ + /// + /// Base class for dynamic + /// implementations that can create new prototype object instances to + /// support a pooling or new-instance-per-invocation strategy. + /// + /// + ///

+ /// All such s must run in an + /// , as they need to + /// call the + /// method to create a new prototype instance. + ///

+ ///
+ /// Rod Johnson + /// Federico Spinazzi (.NET) + public abstract class AbstractPrototypeTargetSource + : ITargetSource, IObjectFactoryAware, IInitializingObject + { + #region Constructor (s) / Destructor + + /// + /// Creates a new instance of the + /// + /// class. + /// + /// + ///

+ /// This is an class, and as such exposes no + /// public constructors. + ///

+ ///
+ protected AbstractPrototypeTargetSource() + { + } + + #endregion + + #region Properties + + /// + /// The name of the target object to be created on each invocation. + /// + /// + ///

+ /// This object should be a prototype, or the same instance will always + /// be obtained from the owning . + ///

+ ///
+ public virtual string TargetObjectName + { + get { return _targetObjectName; } + set { + _targetObjectName = value; + } + } + + /// + /// The of the target object. + /// + public virtual Type TargetType + { + get { return _targetType; } + } + + /// + /// Is the target source static? + /// + /// + /// if the target source is static. + /// + public virtual bool IsStatic + { + get { return false; } + } + + /// + /// The target factory that will be used to perform the lookup + /// of the object referred to by the + /// property. + /// + /// + ///

+ /// Needed so that prototype instances can be created as necessary. + ///

+ ///
+ /// + /// The owning + /// (will never be ). + /// + /// + /// In case of initialization errors. + /// + /// + public virtual IObjectFactory ObjectFactory + { + get { return _owningObjectFactory; } + set + { + _owningObjectFactory = value; + if (!value.IsPrototype(TargetObjectName)) + { + throw new ObjectDefinitionStoreException( + "Cannot use PrototypeTargetSource against a " + + "Singleton object; instances would not be independent."); + } + + #region Instrumentation + + if (logger.IsDebugEnabled) + { + logger.Debug(string.Format( + "Getting object with name '{0}' to determine class.", + TargetObjectName)); + } + + #endregion + + _targetType = _owningObjectFactory.GetType(TargetObjectName); + } + } + + #endregion + + #region Methods + + /// + /// Subclasses should use this method to create a new prototype instance. + /// + protected virtual object NewPrototypeInstance() + { + #region Instrumentation + + if (logger.IsDebugEnabled) + { + logger.Debug(string.Format( + "Creating new target from object '{0}'.", + TargetObjectName)); + } + + #endregion + + return ObjectFactory.GetObject(TargetObjectName); + } + + /// + /// Returns the target object. + /// + /// The target object. + /// + /// If unable to obtain the target object. + /// + public abstract object GetTarget(); + + /// + /// Releases the target object. + /// + /// The target object to release. + public virtual void ReleaseTarget(object target) + { + } + + /// + /// Invoked by an + /// after it has set all object properties supplied + /// (and satisfied the + /// + /// and + /// interfaces). + /// + /// + ///

+ /// Ensures that the property has been + /// set to a valid value (i.e. is not or a string + /// that consists solely of whitespace). + ///

+ ///
+ /// + /// In the event of misconfiguration (such as failure to set an essential + /// property) or if initialization fails. + /// + /// + public virtual void AfterPropertiesSet() + { + AssertUtils.ArgumentHasText( + TargetObjectName, "TargetObjectName", + "The 'TargetObjectName' property must have a value."); + } + + #endregion + #region Fields /// @@ -230,25 +230,25 @@ namespace Spring.Aop.Target public override string ToString() { return GetDescription(); - } - + } + /// /// Returns a textual representation of this target source instance /// - protected virtual string GetDescription() + protected virtual string GetDescription() { return string.Format("[{0}:{1}]", this.GetType().Name, this.TargetObjectName); - } - - /// - /// The shared instance for this class (and derived classes). - /// - protected readonly ILog logger = LogManager.GetLogger(typeof (AbstractPrototypeTargetSource)); - - private String _targetObjectName; - private IObjectFactory _owningObjectFactory; - private Type _targetType; - - #endregion - } + } + + /// + /// The shared instance for this class (and derived classes). + /// + protected readonly ILog logger = LogManager.GetLogger(typeof (AbstractPrototypeTargetSource)); + + private String _targetObjectName; + private IObjectFactory _owningObjectFactory; + private Type _targetType; + + #endregion + } } \ No newline at end of file diff --git a/src/Spring/Spring.Core/Spring.Core.2008.csproj b/src/Spring/Spring.Core/Spring.Core.2008.csproj index 0a49fa7c..7049bf0b 100644 --- a/src/Spring/Spring.Core/Spring.Core.2008.csproj +++ b/src/Spring/Spring.Core/Spring.Core.2008.csproj @@ -1,7 +1,7 @@  Local - 9.0.30729 + 9.0.21022 2.0 {710961A3-0DF4-49E4-A26E-F5B9C044AC84} Debug @@ -1145,6 +1145,7 @@ Code + @@ -1200,6 +1201,7 @@ + Designer diff --git a/src/Spring/Spring.Core/Validation/Actions/ExceptionAction.cs b/src/Spring/Spring.Core/Validation/Actions/ExceptionAction.cs new file mode 100644 index 00000000..88379b4c --- /dev/null +++ b/src/Spring/Spring.Core/Validation/Actions/ExceptionAction.cs @@ -0,0 +1,97 @@ +#region License + +/* + * Copyright 2002-2004 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#endregion + +using System; +using System.Collections; +using Common.Logging; +using Spring.Expressions; +using Spring.Util; + +namespace Spring.Validation.Actions +{ + public class ExceptionAction : BaseValidationAction + { + private ILog log = LogManager.GetLogger(typeof(ExceptionAction)); + private IExpression throwsExpression; + + /// + /// Initializes a new instance of the class. + /// + public ExceptionAction() + { + } + + /// + /// Initializes a new instance of the class. + /// + /// Expression that defines the exception to throw when the validator is not valid. + public ExceptionAction(string exceptionExpression) + : this((exceptionExpression != null ? Expression.Parse(exceptionExpression) : null)) + {} + + /// + /// Initializes a new instance of the class with an expression + /// that defines the exception to throw. + /// + public ExceptionAction(IExpression throwsExpression) + { + this.throwsExpression = throwsExpression; + } + + /// + /// Gets or sets the exception to throw + /// + /// The throws. + public IExpression ThrowsExpression + { + get { return throwsExpression; } + set { throwsExpression = value; } + } + + /// + /// Called when associated validator is invalid. + /// + /// Validation context. + /// Additional context parameters. + /// Validation errors container. + protected override void OnInvalid(object validationContext, IDictionary contextParams, IValidationErrors errors) + { + if (throwsExpression != null) + { + object o = null; + try + { + o = throwsExpression.GetValue(null, contextParams); + } + catch (Exception e) + { + log.Error("Was not able to evaluate action expression [" + throwsExpression + "]", e); + } + Exception exception = o as Exception; + if (exception != null) + { + throw exception; + } + } + throw new ValidationException(errors); + } + + } +} \ No newline at end of file diff --git a/src/Spring/Spring.Core/Validation/Config/ValidationNamespaceParser.cs b/src/Spring/Spring.Core/Validation/Config/ValidationNamespaceParser.cs index 9632964b..dc2984dc 100644 --- a/src/Spring/Spring.Core/Validation/Config/ValidationNamespaceParser.cs +++ b/src/Spring/Spring.Core/Validation/Config/ValidationNamespaceParser.cs @@ -47,7 +47,7 @@ namespace Spring.Validation.Config NamespaceParser( Namespace = "http://www.springframework.net/validation", SchemaLocationAssemblyHint = typeof(ValidationNamespaceParser), - SchemaLocation = "/Spring.Validation.Config/spring-validation-1.1.xsd") + SchemaLocation = "/Spring.Validation.Config/spring-validation-1.3.xsd") ] public sealed class ValidationNamespaceParser : ObjectsNamespaceParser { @@ -167,6 +167,9 @@ namespace Spring.Validation.Config case ValidatorDefinitionConstants.ActionElement: actions.Add(ParseGenericAction(child, childParserContext)); break; + case ValidatorDefinitionConstants.ExceptionElement: + actions.Add(ParseExceptionAction(child, childParserContext)); + break; case ValidatorDefinitionConstants.ReferenceElement: nestedValidators.Add(ParseValidatorReference(child, childParserContext)); break; @@ -280,6 +283,30 @@ namespace Spring.Validation.Config return action; } + private IObjectDefinition ParseExceptionAction(XmlElement element, ParserContext parserContext) + { + string typeName = "Spring.Validation.Actions.ExceptionAction, Spring.Core"; + string throwExpression = GetAttributeValue(element, ValidatorDefinitionConstants.ThrowAttribute); + + + ConstructorArgumentValues ctorArgs = new ConstructorArgumentValues(); + ctorArgs.AddGenericArgumentValue(throwExpression); + + string when = GetAttributeValue(element, ValidatorDefinitionConstants.WhenAttribute); + MutablePropertyValues properties = new MutablePropertyValues(); + if (StringUtils.HasText(when)) + { + properties.Add("When", when); + } + + IConfigurableObjectDefinition action = + parserContext.ReaderContext.ObjectDefinitionFactory.CreateObjectDefinition(typeName, null, parserContext.ReaderContext.Reader.Domain); + action.ConstructorArgumentValues = ctorArgs; + action.PropertyValues = properties; + + return action; + } + /// /// Creates a generic action based on the specified element. /// @@ -335,12 +362,14 @@ namespace Spring.Validation.Config public const string PropertyElement = "property"; public const string MessageElement = "message"; public const string ActionElement = "action"; + public const string ExceptionElement = "exception"; public const string ReferenceElement = "ref"; public const string TypeAttribute = "type"; public const string TestAttribute = "test"; public const string NameAttribute = "name"; public const string WhenAttribute = "when"; + public const string ThrowAttribute = "throw"; public const string PropertyNameAttribute = "name"; diff --git a/src/Spring/Spring.Core/Validation/Config/spring-validation-1.1.xsd b/src/Spring/Spring.Core/Validation/Config/spring-validation-1.1.xsd index 14c99785..b89886f2 100644 --- a/src/Spring/Spring.Core/Validation/Config/spring-validation-1.1.xsd +++ b/src/Spring/Spring.Core/Validation/Config/spring-validation-1.1.xsd @@ -5,7 +5,7 @@ xmlns:vs="http://schemas.microsoft.com/Visual-Studio-Intellisense" targetNamespace="http://www.springframework.net/validation" elementFormDefault="qualified" attributeFormDefault="unqualified" - vs:friendlyname="Spring.NET Validation Framework Configuration" vs:ishtmlschema="false" vs:iscasesensitive="true" vs:requireattributequotes="true" vs:defaultnamespacequalifier="v" vs:defaultnsprefix="v"> + vs:friendlyname="Spring.NET Validation Framework Configuration" vs:ishtmlschema="false" vs:iscasesensitive="true" vs:requireattributequotes="true" vs:defaultnamespacequalifier="" vs:defaultnsprefix=""> @@ -19,259 +19,141 @@ This file defines a configuration schema for the validation framework object definitions. Using elements from this schema instead of the standard object definitions can greatly simplify validator configuration. - ]]> + ]]> - + Defines a message type. - - - - - - - - - - - - + - - - - - - - - - - - - - - - + + + + + + + + Defines a message parameter type. + + - + Defines an action type. - - - - - - - - - - + + - + Defines a validator reference type. - - - - - - - - - - + + - Defines common validator attributes and elements. + Defines base validator type. - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Defines simple validator type. - - - - - - - - - - + + + + + Defines a generic validator type. - - - - - - - - - - - - + + + + + + + + + + Defines a regex validator type. - - - - - The regular expression to match the result of evaluation the 'test' expression against. - - - - + + + + + + + + + Defines a validator group type. - - - - - - - - + + + + - - - - - - - - - - - - - - - - + + + + + + + + + + + + + + + + - Defines a CollectionValidator. + Defines a collection validator group type. - - - Whether to force validating all collection elements, regardless of errors. This attribute is just an alias for 'fast-validate' and kept for backwards compatibility. - - - - - Whether to include individual element's error messages in the resulting list of messages. - - - - - an SpEL expression to narrow the validation context for each element - - + + + - - - Defines a custom validator, allowing to specify the CLR typename of the validator class. - - - - - Defines a RequiredValidator. - - - - - Defines a ConditionValidator. - - - - - Defines a RegularExpressionValidator. - - - - - Defines a ValidatorGroup. - - - - - Defines an AnyValidatorGroup. - - - - - Defines an ExclusiveValidatorGroup. - - + + + + - - - Defines an CollectionValidator. - - + + + + diff --git a/src/Spring/Spring.Core/Validation/Config/spring-validation-1.3.xsd b/src/Spring/Spring.Core/Validation/Config/spring-validation-1.3.xsd new file mode 100644 index 00000000..e646969b --- /dev/null +++ b/src/Spring/Spring.Core/Validation/Config/spring-validation-1.3.xsd @@ -0,0 +1,294 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Defines a validator reference type. + + + + + + + + + + + + + + + + Defines common validator attributes and elements. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Defines simple validator type. + + + + + + + + + + + + + + + Defines a generic validator type. + + + + + + + + + + + + + + + + + + Defines a regex validator type. + + + + + + The regular expression to match the result of evaluation the 'test' expression against. + + + + + + + + + Defines a validator group type. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Defines a CollectionValidator. + + + + + + Whether to force validating all collection elements, regardless of errors. This attribute is just an alias for 'fast-validate' and kept for backwards compatibility. + + + + + Whether to include individual element's error messages in the resulting list of messages. + + + + + an SpEL expression to narrow the validation context for each element + + + + + + + + + Defines a custom validator, allowing to specify the CLR typename of the validator class. + + + + + Defines a RequiredValidator. + + + + + Defines a ConditionValidator. + + + + + Defines a RegularExpressionValidator. + + + + + Defines a ValidatorGroup. + + + + + Defines an AnyValidatorGroup. + + + + + Defines an ExclusiveValidatorGroup. + + + + + + Defines an CollectionValidator. + + + + diff --git a/test/Spring/Spring.Core.Tests/Objects/TestObject.cs b/test/Spring/Spring.Core.Tests/Objects/TestObject.cs index 1ccf64e0..aea0cda3 100644 --- a/test/Spring/Spring.Core.Tests/Objects/TestObject.cs +++ b/test/Spring/Spring.Core.Tests/Objects/TestObject.cs @@ -22,10 +22,10 @@ using System; using System.Collections; -using System.Collections.Generic; #if !NET_1_1 -using System.Collections.Specialized; +using System.Collections.Generic; #endif +using System.Collections.Specialized; using System.ComponentModel; using System.ComponentModel.Design.Serialization; using System.Drawing; @@ -408,7 +408,9 @@ namespace Spring.Objects private IDictionary sharedState; private NameValueCollection someNameValueCollection; +#if !NET_1_1 private List someGenericStringList; +#endif #endregion diff --git a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2008.csproj b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2008.csproj index 5ca5a1ed..725e52b8 100644 --- a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2008.csproj +++ b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2008.csproj @@ -722,6 +722,7 @@ + @@ -811,8 +812,8 @@ + - @@ -853,7 +854,6 @@ - diff --git a/test/Spring/Spring.Core.Tests/Validation/Actions/ExceptionActionTests.cs b/test/Spring/Spring.Core.Tests/Validation/Actions/ExceptionActionTests.cs new file mode 100644 index 00000000..9441b896 --- /dev/null +++ b/test/Spring/Spring.Core.Tests/Validation/Actions/ExceptionActionTests.cs @@ -0,0 +1,109 @@ +#region License + +/* + * Copyright 2002-2004 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#endregion + +using System; +using System.Collections; + +using NUnit.Framework; + +using Spring.Expressions; + +namespace Spring.Validation.Actions +{ + /// + /// Tests for the ExceptionAction class. + /// + /// Mark Pollack + [TestFixture] + public class ExceptionActionTests + { + + [Test] + public void WhenInvalidThrowDefaultException() + { + Inventor context = new Inventor("Nikola Tesla", new DateTime(1856, 7, 9), "Serbian"); + IDictionary vars = new Hashtable(); + ExceptionAction action = new ExceptionAction(); + try + { + action.Execute(false, context, vars, null); + Assert.Fail("Should have thrown exception"); + } + catch (ValidationException) + { + + } + } + + [Test] + public void WhenInvalidThrowCustomException() + { + Inventor context = new Inventor("Nikola Tesla", new DateTime(1856, 7, 9), "Serbian"); + IDictionary vars = new Hashtable(); + ExceptionAction action = new ExceptionAction("new System.InvalidOperationException('invalid')"); + try + { + action.Execute(false, context, vars, null); + Assert.Fail("Should have thrown exception"); + } + catch (InvalidOperationException e) + { + Assert.AreEqual("invalid", e.Message); + } + } + + [Test] + public void WhenInvalidThrowCustomExceptionUsingSetter() + { + Inventor context = new Inventor("Nikola Tesla", new DateTime(1856, 7, 9), "Serbian"); + IDictionary vars = new Hashtable(); + ExceptionAction action = new ExceptionAction(); + IExpression expression = Expression.Parse("new System.InvalidOperationException('invalid')"); + action.ThrowsExpression = expression; + try + { + action.Execute(false, context, vars, null); + Assert.Fail("Should have thrown exception"); + } + catch (InvalidOperationException e) + { + Assert.AreEqual("invalid", e.Message); + } + } + + + [Test] + public void WhenValid() + { + Inventor context = new Inventor("Nikola Tesla", new DateTime(1856, 7, 9), "Serbian"); + IDictionary vars = new Hashtable(); + ExceptionAction action = new ExceptionAction(); + try + { + action.Execute(true, context, vars, null); + } + catch (Exception) + { + Assert.Fail("Should not have thrown exception"); + } + } + + } +} \ No newline at end of file diff --git a/test/Spring/Spring.Core.Tests/Validation/ValidationNamespaceParserTests.cs b/test/Spring/Spring.Core.Tests/Validation/ValidationNamespaceParserTests.cs index 97f4ba1c..430bf124 100644 --- a/test/Spring/Spring.Core.Tests/Validation/ValidationNamespaceParserTests.cs +++ b/test/Spring/Spring.Core.Tests/Validation/ValidationNamespaceParserTests.cs @@ -65,7 +65,7 @@ namespace Spring.Validation } } IObjectDefinition[] defs = registry.GetObjectDefinitions(); - Assert.AreEqual(8, defs.Length); + Assert.AreEqual(9, defs.Length); IObjectDefinition def = registry.GetObjectDefinition("destinationAirportValidator"); Assert.IsTrue(def.IsSingleton); @@ -89,7 +89,8 @@ namespace Spring.Validation Assert.AreEqual(typeof(RegularExpressionValidator), def.ObjectType); Assert.AreEqual("[A-Z]*", def.PropertyValues.GetPropertyValue("Expression").Value); - def = registry.GetObjectDefinition("airportCodeValidator"); + + def = registry.GetObjectDefinition("simpleAirportValidator"); Assert.IsTrue(def.IsSingleton); Assert.IsTrue(def.IsLazyInit); Assert.IsTrue(typeof(IValidator).IsAssignableFrom(def.ObjectType)); @@ -98,6 +99,22 @@ namespace Spring.Validation object actionsObject = actionsProperty.Value; Assert.AreEqual(typeof(ManagedList), actionsObject.GetType()); ManagedList actions = (ManagedList)actionsObject; + Assert.AreEqual(1, actions.Count); + + IObjectDefinition exceptionActionDefinition = (IObjectDefinition)actions[0]; + Assert.AreEqual(typeof(ExceptionAction), exceptionActionDefinition.ObjectType); + Assert.AreEqual("'new System.InvalidOperationException(\"invalid\")' []", exceptionActionDefinition.ConstructorArgumentValues.GenericArgumentValues[0].ToString()); + // + + def = registry.GetObjectDefinition("airportCodeValidator"); + Assert.IsTrue(def.IsSingleton); + Assert.IsTrue(def.IsLazyInit); + Assert.IsTrue(typeof(IValidator).IsAssignableFrom(def.ObjectType)); + actionsProperty = def.PropertyValues.GetPropertyValue("Actions"); + Assert.IsNotNull(actionsProperty); + actionsObject = actionsProperty.Value; + Assert.AreEqual(typeof(ManagedList), actionsObject.GetType()); + actions = (ManagedList)actionsObject; Assert.AreEqual(4, actions.Count); IObjectDefinition messageDefinition = (IObjectDefinition)actions[1]; @@ -110,7 +127,7 @@ namespace Spring.Validation private XmlDocument GetValidatedXmlResource(string resourceExtension) { - AssemblyResource validationSchema = new AssemblyResource("assembly://Spring.Core/Spring.Validation.Config/spring-validation-1.1.xsd"); + AssemblyResource validationSchema = new AssemblyResource("assembly://Spring.Core/Spring.Validation.Config/spring-validation-1.3.xsd"); AssemblyResource objectsSchema = new AssemblyResource("assembly://Spring.Core/Spring.Objects.Factory.Xml/spring-objects-1.3.xsd"); return TestResourceLoader.GetXmlValidated(this, resourceExtension, objectsSchema, validationSchema); diff --git a/test/Spring/Spring.Core.Tests/Validation/ValidationNamespaceParserTests_WhenConfigFileIsValid.xml b/test/Spring/Spring.Core.Tests/Validation/ValidationNamespaceParserTests_WhenConfigFileIsValid.xml index 62bda7f5..fa4512c2 100644 --- a/test/Spring/Spring.Core.Tests/Validation/ValidationNamespaceParserTests_WhenConfigFileIsValid.xml +++ b/test/Spring/Spring.Core.Tests/Validation/ValidationNamespaceParserTests_WhenConfigFileIsValid.xml @@ -18,13 +18,18 @@ - + + + + + +