diff --git a/src/Spring/Spring.Core/Context/Support/ContextHandler.cs b/src/Spring/Spring.Core/Context/Support/ContextHandler.cs index f0018d4a..e6ff0fd5 100644 --- a/src/Spring/Spring.Core/Context/Support/ContextHandler.cs +++ b/src/Spring/Spring.Core/Context/Support/ContextHandler.cs @@ -1,7 +1,7 @@ #region License /* - * Copyright © 2002-2005 the original author or authors. + * 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. @@ -30,6 +30,7 @@ using Common.Logging; using Spring.Core; using Spring.Core.TypeResolution; using Spring.Objects; +using Spring.Reflection.Dynamic; using Spring.Util; #endregion @@ -546,8 +547,7 @@ namespace Spring.Context.Support protected override IApplicationContext InvokeContextConstructor( ConstructorInfo ctor) { - return (IApplicationContext) ObjectUtils.InstantiateType( - ctor, new object[] {ContextName, CaseSensitive, Resources}); + return (IApplicationContext)(new SafeConstructor(ctor).Invoke(new object[] {ContextName, CaseSensitive, Resources})); } } @@ -574,8 +574,7 @@ namespace Spring.Context.Support protected override IApplicationContext InvokeContextConstructor( ConstructorInfo ctor) { - return (IApplicationContext) ObjectUtils.InstantiateType( - ctor, new object[] {ContextName, CaseSensitive, this.parentContext, Resources}); + return (IApplicationContext)(new SafeConstructor(ctor).Invoke(new object[] {ContextName, CaseSensitive, this.parentContext, Resources})); } private IApplicationContext parentContext; @@ -638,4 +637,4 @@ namespace Spring.Context.Support #endregion } -} \ No newline at end of file +} diff --git a/src/Spring/Spring.Core/Objects/Factory/ObjectDefinitionStoreException.cs b/src/Spring/Spring.Core/Objects/Factory/ObjectDefinitionStoreException.cs index 4aeb1253..93b67076 100644 --- a/src/Spring/Spring.Core/Objects/Factory/ObjectDefinitionStoreException.cs +++ b/src/Spring/Spring.Core/Objects/Factory/ObjectDefinitionStoreException.cs @@ -1,7 +1,7 @@ #region License /* - * Copyright © 2002-2005 the original author or authors. + * 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. @@ -139,9 +139,8 @@ namespace Spring.Objects.Factory IResource resourceLocation, string name, string message, - Exception rootCause) : this - (resourceLocation == null ? string.Empty : resourceLocation.Description, - name, message, rootCause) + Exception rootCause) + : this( (resourceLocation == null ? string.Empty : resourceLocation.Description), name, message, rootCause) { } @@ -165,10 +164,10 @@ namespace Spring.Objects.Factory string name, string message, Exception rootCause) - : base( + : base( string.Format( - "Error registering object with name '{0}' defined in '{1}' : {2}", - name, + "Error registering object {0}defined in '{1}' : {2}", + name == null ? string.Empty : string.Format("with name '{0}' ", name), resourceDescription, message), rootCause) @@ -257,4 +256,4 @@ namespace Spring.Objects.Factory /// protected string _objectName = string.Empty; } -} \ No newline at end of file +} diff --git a/src/Spring/Spring.Core/Objects/Factory/Xml/DefaultObjectDefinitionDocumentReader.cs b/src/Spring/Spring.Core/Objects/Factory/Xml/DefaultObjectDefinitionDocumentReader.cs index ce2db6fd..d6c2d972 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Xml/DefaultObjectDefinitionDocumentReader.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Xml/DefaultObjectDefinitionDocumentReader.cs @@ -1,7 +1,7 @@ #region License /* - * Copyright © 2002-2005 the original author or authors. + * 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. @@ -149,6 +149,9 @@ namespace Spring.Objects.Factory.Xml /// /// The root element to start parsing from. /// The instance to use. + /// + /// in case an error happens during parsing and registering object definitions + /// protected virtual void ParseObjectDefinitions(XmlElement root, ObjectDefinitionParserHelper helper) { foreach (XmlNode node in root.ChildNodes) @@ -156,34 +159,24 @@ namespace Spring.Objects.Factory.Xml if (node.NodeType == XmlNodeType.Element) { XmlElement element = (XmlElement) node; - INamespaceParser parser = GetNamespaceParser(element, helper); - ParserContext parserContext = new ParserContext(helper.ReaderContext, helper); - parser.ParseElement(element, parserContext); + try + { + INamespaceParser parser = GetNamespaceParser(element, helper); + ParserContext parserContext = new ParserContext(helper.ReaderContext, helper); + parser.ParseElement(element, parserContext); + } + catch( ObjectDefinitionStoreException ) + { + throw; + } + catch (Exception ex) + { + helper.ReaderContext.ReportException(node, null, "Failed parsing element", ex); + } } } } - /// - /// Parses the default element. - /// - /// The element. - /// The helper. - private void ParseDefaultElement(XmlElement element, ObjectDefinitionParserHelper helper) - { - if (element.LocalName == ObjectDefinitionConstants.ImportElement) - { - ImportObjectDefinitionResource(element); - } - else if (element.LocalName == ObjectDefinitionConstants.AliasElement) - { - ParseAlias(element, ReaderContext.Registry); - } - else if (element.LocalName == ObjectDefinitionConstants.ObjectElement) - { - RegisterObjectDefinition(element, helper); - } - } - /// /// Loads external XML object definitions from the resource described by the supplied /// . @@ -337,4 +330,4 @@ namespace Spring.Objects.Factory.Xml #endregion } -} \ No newline at end of file +} diff --git a/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectsNamespaceParser.cs b/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectsNamespaceParser.cs index 7c0d6278..e26bb560 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectsNamespaceParser.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Xml/ObjectsNamespaceParser.cs @@ -1,7 +1,7 @@ #region License /* - * Copyright © 2002-2005 the original author or authors. + * 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. @@ -278,9 +278,14 @@ namespace Spring.Objects.Factory.Xml return; } } + catch(ObjectDefinitionStoreException) + { + throw; + } catch (Exception ex) { - throw new ObjectDefinitionStoreException(string.Format("Failed parsing object definition '{0}'", element.OuterXml), ex); + //throw new ObjectDefinitionStoreException(string.Format("Failed parsing object definition '{0}'", element.OuterXml), ex); + parserContext.ReaderContext.ReportException(element, null, null, ex); } @@ -340,6 +345,7 @@ namespace Spring.Objects.Factory.Xml string objectName = id; if (StringUtils.IsNullOrEmpty(objectName)) { + // TODO (EE): pass parserContext to CalculateId as well (resolving relative Urls in WebApps is parserContext-dependent) (EE) objectName = CalculateId(element, aliases); } @@ -540,7 +546,7 @@ namespace Spring.Objects.Factory.Xml typeName), ex); } - catch (ApplicationException ex) + catch (Exception ex) { parserContext.ReaderContext.ReportException(element, id, string.Empty, ex); } @@ -1433,4 +1439,4 @@ namespace Spring.Objects.Factory.Xml return StringUtils.HasText(element.Prefix) ? element.Prefix : "spring"; } } -} \ No newline at end of file +} diff --git a/src/Spring/Spring.Core/Objects/Factory/Xml/XmlObjectDefinitionReader.cs b/src/Spring/Spring.Core/Objects/Factory/Xml/XmlObjectDefinitionReader.cs index 03eaff4c..e3097d01 100644 --- a/src/Spring/Spring.Core/Objects/Factory/Xml/XmlObjectDefinitionReader.cs +++ b/src/Spring/Spring.Core/Objects/Factory/Xml/XmlObjectDefinitionReader.cs @@ -1,7 +1,7 @@ #region License /* - * Copyright © 2002-2005 the original author or authors. + * 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. @@ -231,6 +231,10 @@ namespace Spring.Objects.Factory.Xml "Line " + ex.LineNumber + " in XML document from " + resource + " is invalid. " + ex.Message, ex); } + catch(ObjectDefinitionStoreException) + { + throw; + } catch (Exception ex) { throw new ObjectDefinitionStoreException("Unexpected exception parsing XML document from " + resource.Description + "Inner exception message= " + ex.Message, ex); diff --git a/src/Spring/Spring.Core/Util/ObjectUtils.cs b/src/Spring/Spring.Core/Util/ObjectUtils.cs index 937ccc2c..ea048574 100644 --- a/src/Spring/Spring.Core/Util/ObjectUtils.cs +++ b/src/Spring/Spring.Core/Util/ObjectUtils.cs @@ -1,7 +1,7 @@ #region License /* - * Copyright © 2002-2005 the original author or authors. + * 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. @@ -27,6 +27,7 @@ using System.Reflection; using System.Runtime.Remoting; using Common.Logging; using Spring.Objects; +using Spring.Reflection.Dynamic; #endregion @@ -246,7 +247,9 @@ namespace Spring.Util #endif try { - return constructor.Invoke(arguments); + // replaced with SafeConstructor() to avoid nasty "TargetInvocationException"s + //return constructor.Invoke(arguments); + return (new SafeConstructor(constructor)).Invoke(arguments); } catch (Exception ex) { @@ -542,4 +545,4 @@ namespace Spring.Util return hashcode.ToString("X6"); } } -} \ No newline at end of file +} diff --git a/test/Spring/Spring.Core.Tests/Context/Support/ContextLocatorHandlerTests.cs b/test/Spring/Spring.Core.Tests/Context/Support/ContextLocatorHandlerTests.cs index 0b040436..0de5a43f 100644 --- a/test/Spring/Spring.Core.Tests/Context/Support/ContextLocatorHandlerTests.cs +++ b/test/Spring/Spring.Core.Tests/Context/Support/ContextLocatorHandlerTests.cs @@ -27,6 +27,7 @@ using System.Security.Policy; using System.Xml; using NUnit.Framework; using Spring.Objects; +using Spring.Objects.Factory; using Spring.Util; #endregion @@ -64,6 +65,48 @@ namespace Spring.Context.Support Assert.AreEqual(1, ContextRegistry.GetContext().ObjectDefinitionCount); } + [Test] + public void CreateRootContextFailure() + { + const string xmlData = + @" + +"; + CreateConfigurationElement(xmlData); + + ContextHandler ctxHandler = new ContextHandler(); + try + { + IApplicationContext ctx = (IApplicationContext) ctxHandler.Create(null, null, configurationElement); + Assert.Fail(""); + } + catch(ConfigurationException cfgex) + { + Assert.IsInstanceOfType( typeof(ObjectDefinitionStoreException), cfgex.InnerException ); + } + } + + [Test] + public void CreateChildContextFailure() + { + const string xmlData = + @" + +"; + CreateConfigurationElement(xmlData); + + ContextHandler ctxHandler = new ContextHandler(); + try + { + IApplicationContext ctx = (IApplicationContext) ctxHandler.Create(new StaticApplicationContext(), null, configurationElement); + Assert.Fail(""); + } + catch(ConfigurationException cfgex) + { + Assert.IsInstanceOfType( typeof(ObjectDefinitionStoreException), cfgex.InnerException ); + } + } + /// /// Expect failure when using a type that does not inherit from IApplicationContext /// diff --git a/test/Spring/Spring.Core.Tests/Core/IO/ConfigSectionResourceTests.cs b/test/Spring/Spring.Core.Tests/Core/IO/ConfigSectionResourceTests.cs new file mode 100644 index 00000000..85804285 --- /dev/null +++ b/test/Spring/Spring.Core.Tests/Core/IO/ConfigSectionResourceTests.cs @@ -0,0 +1,18 @@ +using System.Xml; +using NUnit.Framework; + +namespace Spring.Core.IO +{ + /// + /// Summary description for ConfigSectionResourceTests. + /// + [TestFixture] + public class ConfigSectionResourceTests + { + [Test] + public void CanCreate() + { + // TODO + } + } +} \ No newline at end of file diff --git a/test/Spring/Spring.Core.Tests/Core/IO/ConfigSectionResourceTests_config1.xml b/test/Spring/Spring.Core.Tests/Core/IO/ConfigSectionResourceTests_config1.xml new file mode 100644 index 00000000..4889852c --- /dev/null +++ b/test/Spring/Spring.Core.Tests/Core/IO/ConfigSectionResourceTests_config1.xml @@ -0,0 +1,19 @@ + + + + +
+ + + + + + + + + + + + + + diff --git a/test/Spring/Spring.Core.Tests/DataBinding/SimpleExpressionBindingTests.cs b/test/Spring/Spring.Core.Tests/DataBinding/SimpleExpressionBindingTests.cs index ce99d4a9..ead85330 100644 --- a/test/Spring/Spring.Core.Tests/DataBinding/SimpleExpressionBindingTests.cs +++ b/test/Spring/Spring.Core.Tests/DataBinding/SimpleExpressionBindingTests.cs @@ -33,7 +33,8 @@ namespace Spring.DataBinding #if NET_2_0 private class BindToNullable_TestEntity { - public Nullable SortOrder { get;set; } + private Nullable sortOrder; + public Nullable SortOrder { get { return sortOrder; } set { sortOrder = value; } } } [Test(Description="http://jira.springframework.org/browse/SPRNET-996")] diff --git a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2003.csproj b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2003.csproj index 61ea52cc..30edb8a8 100644 --- a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2003.csproj +++ b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2003.csproj @@ -132,6 +132,11 @@ AssemblyName = "System.Windows.Forms" HintPath = "C:\WINDOWS\Microsoft.NET\Framework\v1.1.4322\System.Windows.Forms.dll" /> + @@ -192,6 +197,11 @@ RelPath = "TestResource.txt" BuildAction = "EmbeddedResource" /> + + + Code + @@ -655,6 +656,7 @@ Code + @@ -755,6 +757,7 @@ + diff --git a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.build b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.build index 1b960af1..d4f997a0 100644 --- a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.build +++ b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.build @@ -33,11 +33,14 @@ + + diff --git a/test/Spring/Spring.Core.Tests/TestResourceLoader.cs b/test/Spring/Spring.Core.Tests/TestResourceLoader.cs new file mode 100644 index 00000000..19b680e6 --- /dev/null +++ b/test/Spring/Spring.Core.Tests/TestResourceLoader.cs @@ -0,0 +1,103 @@ +using System; +using System.IO; +using System.Net; +using System.Web; +using System.Xml; +using NUnit.Framework; + +namespace Spring +{ + /// + /// Supports obtaining embedded resources from assembly. + /// + /// + /// The first context argument is always the namespace scope to be used for resolving resource names. + /// + public class TestResourceLoader + { + #region WebRequest + + public class TestResourceWebResponse : WebResponse + { + private Type resourceType; + private string resourceName; + + public TestResourceWebResponse(Uri requestUri) + { + string typeName = HttpUtility.UrlDecode(requestUri.AbsolutePath.Substring(1)); // strip leading '/' + resourceType = Type.GetType(typeName, true); + resourceName = HttpUtility.UrlDecode(requestUri.Fragment.Substring(1)); // strip leading '#' + } + + public override System.IO.Stream GetResponseStream() + { + Stream stm = TestResourceLoader.GetStream(resourceType, resourceName); + return stm; + } + } + + public class TestResourceWebRequest : WebRequest + { + private Uri requestUri; + + public TestResourceWebRequest(Uri requestUri) + { + this.requestUri = requestUri; + } + + public override WebResponse GetResponse() + { + return new TestResourceWebResponse(requestUri); + } + + } + + public class TestResourceWebRequestFactory : IWebRequestCreate + { + public WebRequest Create(Uri uri) + { + return new TestResourceWebRequest(uri); + } + } + + #endregion + + static TestResourceLoader() + { + WebRequest.RegisterPrefix("testres", new TestResourceWebRequestFactory()); + } + + private TestResourceLoader() + {} + + public static Uri GetUri(object context, string ext) + { + string resname = context.GetType().AssemblyQualifiedName + "#" + ext; + Uri uri = new Uri("testres://(local)/" + resname, false); + return uri; + } + + public static string GetText(object context, string ext) + { + Stream stm = GetStream(context, ext); + return new StreamReader(stm).ReadToEnd(); + } + + public static XmlDocument GetXml(object context, string ext) + { + Stream stm = GetStream(context, ext); + XmlDocument xmlDoc = new XmlDocument(); + xmlDoc.Load( stm ); + return xmlDoc; + } + + public static Stream GetStream(object context, string ext) + { + Type contextType = (context is Type) ? (Type)context : context.GetType(); + string resname = contextType.FullName + ext; + Stream stm = contextType.Assembly.GetManifestResourceStream(resname); + Assert.IsNotNull(stm, "Resource '{0}' in assembly '{1}' not found", resname, contextType.Assembly.FullName); + return stm; + } + } +} diff --git a/test/Spring/Spring.Core.Tests/Util/ObjectUtilsTests.cs b/test/Spring/Spring.Core.Tests/Util/ObjectUtilsTests.cs index a41555ec..991bf067 100644 --- a/test/Spring/Spring.Core.Tests/Util/ObjectUtilsTests.cs +++ b/test/Spring/Spring.Core.Tests/Util/ObjectUtilsTests.cs @@ -26,9 +26,11 @@ using System.Collections; using System.Collections.Generic; #endif using System.Reflection; +using System.Runtime.Serialization; using System.Security.Policy; using NUnit.Framework; using Spring.Objects; +using Spring.Objects.Factory; using Spring.Util; #endregion @@ -116,6 +118,22 @@ namespace Spring.Util Assert.IsNotNull(foo, "Failed to instantiate an instance of a valid Type."); Assert.IsTrue(foo is TestObject, "The instantiated instance was not an instance of the type that was passed in."); } + + [Test] + public void InstantiateTypeThrowingWithinPublicConstructor() + { + try + { + ObjectUtils.InstantiateType(typeof(ThrowingWithinConstructor)); + Assert.Fail(); + } + catch(FatalReflectionException ex) + { + // no nasty "TargetInvocationException" is in between! + Assert.AreEqual( typeof(ThrowingWithinConstructorException), ex.InnerException.GetType() ); + } + } + #if NET_2_0 [Test] [ExpectedException(typeof(FatalReflectionException))] @@ -348,6 +366,29 @@ namespace Spring.Util private string _name; } + [Serializable] + private class ThrowingWithinConstructorException : TestException + { + public ThrowingWithinConstructorException() + {} + + public ThrowingWithinConstructorException(string message) : base(message) + {} + + public ThrowingWithinConstructorException(string message, Exception inner) : base(message, inner) + {} + + protected ThrowingWithinConstructorException(SerializationInfo info, StreamingContext context) : base(info, context) + {} + } + + public class ThrowingWithinConstructor + { + public ThrowingWithinConstructor() + { + throw new ThrowingWithinConstructorException(); + } + } #endregion } } \ No newline at end of file diff --git a/test/Spring/Spring.Web.Tests/Spring.Web.Tests.2003.csproj b/test/Spring/Spring.Web.Tests/Spring.Web.Tests.2003.csproj index 4abdc4fb..85f925e0 100644 --- a/test/Spring/Spring.Web.Tests/Spring.Web.Tests.2003.csproj +++ b/test/Spring/Spring.Web.Tests/Spring.Web.Tests.2003.csproj @@ -321,7 +321,7 @@ />