diff --git a/src/Spring/Spring.Core/Core/IO/AbstractResource.cs b/src/Spring/Spring.Core/Core/IO/AbstractResource.cs
index 8ac9ee46..7c496965 100644
--- a/src/Spring/Spring.Core/Core/IO/AbstractResource.cs
+++ b/src/Spring/Spring.Core/Core/IO/AbstractResource.cs
@@ -71,6 +71,7 @@ namespace Spring.Core.IO
protected const string DefaultBasePathPlaceHolder = "~";
private string protocol;
+ private string resourceName;
private string basePathPlaceHolder = DefaultBasePathPlaceHolder;
#region Constructor (s) / Destructor
@@ -109,7 +110,8 @@ namespace Spring.Core.IO
protected AbstractResource(string resourceName)
{
AssertUtils.ArgumentHasText(resourceName, "resourceName");
- protocol = ConfigurableResourceLoader.GetProtocol(resourceName);
+ this.protocol = ConfigurableResourceLoader.GetProtocol(resourceName);
+ this.resourceName = resourceName;
}
#endregion
@@ -196,6 +198,7 @@ namespace Spring.Core.IO
get { return false; }
}
+#if !NET_2_0
///
/// Returns the handle for this resource.
///
@@ -222,7 +225,19 @@ namespace Spring.Core.IO
Description + " cannot be resolved to a Uri.");
}
}
-
+#else
+ ///
+ /// Returns the handle for this resource.
+ ///
+ ///
+ public virtual Uri Uri
+ {
+ get
+ {
+ return new Uri(resourceName);
+ }
+ }
+#endif
///
/// Returns a handle for this resource.
///
diff --git a/src/Spring/Spring.Core/Core/IO/AssemblyResource.cs b/src/Spring/Spring.Core/Core/IO/AssemblyResource.cs
index 8f4d8dd5..163c6028 100644
--- a/src/Spring/Spring.Core/Core/IO/AssemblyResource.cs
+++ b/src/Spring/Spring.Core/Core/IO/AssemblyResource.cs
@@ -248,6 +248,19 @@ namespace Spring.Core.IO
}
}
+#if NET_2_0
+ ///
+ /// Returns the handle for this resource.
+ ///
+ ///
+ public override Uri Uri
+ {
+ get
+ {
+ return new Uri(_fullResourceName);
+ }
+ }
+#endif
#endregion
///
diff --git a/src/Spring/Spring.Core/Core/IO/ResourceHandlerRegistry.cs b/src/Spring/Spring.Core/Core/IO/ResourceHandlerRegistry.cs
index bb3ab665..fcf3698c 100644
--- a/src/Spring/Spring.Core/Core/IO/ResourceHandlerRegistry.cs
+++ b/src/Spring/Spring.Core/Core/IO/ResourceHandlerRegistry.cs
@@ -110,14 +110,14 @@ namespace Spring.Core.IO
{
lock (resourceHandlers.SyncRoot)
{
- resourceHandlers["config"] = GetResourceConstructor(typeof(ConfigSectionResource));
- resourceHandlers["file"] = GetResourceConstructor(typeof(FileSystemResource));
- resourceHandlers["http"] = GetResourceConstructor(typeof(UrlResource));
- resourceHandlers["https"] = GetResourceConstructor(typeof(UrlResource));
+ RegisterResourceHandler("config", typeof(ConfigSectionResource));
+ RegisterResourceHandler("file", typeof(FileSystemResource));
+ RegisterResourceHandler("http", typeof(UrlResource));
+ RegisterResourceHandler("https", typeof(UrlResource));
#if NET_2_0
- resourceHandlers["ftp"] = GetResourceConstructor(typeof(UrlResource));
+ RegisterResourceHandler("ftp", typeof(UrlResource));
#endif
- resourceHandlers["assembly"] = GetResourceConstructor(typeof(AssemblyResource));
+ RegisterResourceHandler("assembly", typeof(AssemblyResource));
// register custom resource handlers
ConfigurationUtils.GetSection(ResourcesSectionName);
@@ -244,11 +244,34 @@ namespace Spring.Core.IO
lock (resourceHandlers.SyncRoot)
{
+#if NET_2_0
+ // register generic uri parser for this scheme
+ if (!UriParser.IsKnownScheme(protocolName))
+ {
+ UriParser.Register(new TolerantUriParser(), protocolName, 0);
+ }
+#endif
IDynamicConstructor ctor = GetResourceConstructor(handlerType);
resourceHandlers[protocolName] = ctor;
}
}
+#if NET_2_0
+ ///
+ /// Allows to create any arbitrary Url format
+ ///
+ private class TolerantUriParser : GenericUriParser
+ {
+ private const GenericUriParserOptions DefaultOptions = GenericUriParserOptions.Default
+ |GenericUriParserOptions.GenericAuthority
+ |GenericUriParserOptions.AllowEmptyAuthority;
+
+ public TolerantUriParser()
+ : base(DefaultOptions)
+ {}
+ }
+#endif
+
private static IDynamicConstructor GetResourceConstructor(Type handlerType)
{
ConstructorInfo ctor = handlerType.GetConstructor(new Type[] {typeof(string)});
diff --git a/src/Spring/Spring.Core/Objects/Factory/Xml/NamespaceParserRegistry.cs b/src/Spring/Spring.Core/Objects/Factory/Xml/NamespaceParserRegistry.cs
index cc8d7d0a..73caf7af 100644
--- a/src/Spring/Spring.Core/Objects/Factory/Xml/NamespaceParserRegistry.cs
+++ b/src/Spring/Spring.Core/Objects/Factory/Xml/NamespaceParserRegistry.cs
@@ -47,6 +47,26 @@ namespace Spring.Objects.Factory.Xml
/// Aleksandar Seovic
public class NamespaceParserRegistry
{
+ ///
+ /// Resolves xml entities by using the infrastructure.
+ ///
+ private class XmlResourceUrlResolver : XmlUrlResolver
+ {
+ public override object GetEntity( Uri absoluteUri, string role, Type ofObjectToReturn )
+ {
+ IResourceLoader resourceLoader = new ConfigurableResourceLoader();
+ IResource resource = resourceLoader.GetResource(absoluteUri.AbsoluteUri);
+ return resource.InputStream;
+ //return base.GetEntity( absoluteUri, role, ofObjectToReturn );
+ }
+
+ public override Uri ResolveUri( Uri baseUri, string relativeUri )
+ {
+ // TODO: resolve Uri using IResource instance
+ return base.ResolveUri( baseUri, relativeUri );
+ }
+ }
+
///
/// Name of the .Net config section that contains definitions
/// for custom config parsers.
@@ -55,12 +75,12 @@ namespace Spring.Objects.Factory.Xml
#region Fields
- private static IDictionary parsers = new HybridDictionary();
+ private readonly static IDictionary parsers;
#if !NET_2_0
- private static XmlSchemaCollection schemas = new XmlSchemaCollection();
+ private readonly static XmlSchemaCollection schemas;
#else
- private static XmlSchemaSet schemas = new XmlSchemaSet();
+ private readonly static XmlSchemaSet schemas;
#endif
#endregion
@@ -70,19 +90,23 @@ namespace Spring.Objects.Factory.Xml
///
static NamespaceParserRegistry()
{
- lock (parsers.SyncRoot)
- lock (schemas)
- {
- //TODO - externalize default list of parsers.
- RegisterParser(new ObjectsNamespaceParser());
- //This is done simple as a means to avoid cyclic dependencies with Factory.Xml
- //which implementations of parsers typically use.
- RegisterParser(ObjectUtils.InstantiateType(typeof(NamespaceParserRegistry).Assembly,
- "Spring.Validation.Config.ValidationNamespaceParser") as INamespaceParser);
+ parsers = new HybridDictionary();
+#if !NET_2_0
+ schemas = new XmlSchemaCollection();
+#else
+ schemas = new XmlSchemaSet();
+ schemas.XmlResolver = new XmlResourceUrlResolver();
+#endif
- // register custom config parsers
- ConfigurationUtils.GetSection(ConfigParsersSectionName);
- }
+ //TODO - externalize default list of parsers.
+ RegisterParser(new ObjectsNamespaceParser());
+ //This is done simple as a means to avoid cyclic dependencies with Factory.Xml
+ //which implementations of parsers typically use.
+ RegisterParser(ObjectUtils.InstantiateType(typeof(NamespaceParserRegistry).Assembly,
+ "Spring.Validation.Config.ValidationNamespaceParser") as INamespaceParser);
+
+ // register custom config parsers
+ ConfigurationUtils.GetSection(ConfigParsersSectionName);
}
///
@@ -280,9 +304,20 @@ namespace Spring.Objects.Factory.Xml
{
IResourceLoader resourceLoader = new ConfigurableResourceLoader();
IResource schema = resourceLoader.GetResource(schemaLocation);
- try {
- schemas.Add(namespaceUri, new XmlTextReader(schema.InputStream));
- } catch (Exception e)
+ try
+ {
+#if NET_1_0
+ XmlTextReader schemaDocument = new XmlTextReader(schemaLocation, schema.InputStream);
+ schemas.Add(namespaceUri, schemaDocument);
+#elif NET_1_1
+ XmlTextReader schemaDocument = new XmlTextReader(schemaLocation, schema.InputStream);
+ schemas.Add(namespaceUri, schemaDocument, new XmlResourceUrlResolver());
+#else
+ XmlTextReader schemaDocument = new XmlTextReader(schema.Uri.AbsoluteUri, schema.InputStream);
+ schemas.Add(namespaceUri, schemaDocument);
+#endif
+ }
+ catch (Exception e)
{
throw new ArgumentException("Could not load schema from resource = " + schema, e);
}
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Xml/NamespaceParserRegistryTests.cs b/test/Spring/Spring.Core.Tests/Objects/Factory/Xml/NamespaceParserRegistryTests.cs
new file mode 100644
index 00000000..ddf412f3
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Xml/NamespaceParserRegistryTests.cs
@@ -0,0 +1,82 @@
+#region License
+
+/*
+ * Copyright © 2002-2008 the original author or authors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#endregion
+
+#region Imports
+
+using System;
+using System.IO;
+using System.Xml;
+using System.Xml.Schema;
+using NUnit.Framework;
+using Spring.Core.IO;
+using Spring.Objects.Factory.Config;
+using Spring.Util;
+
+#endregion
+
+namespace Spring.Objects.Factory.Xml
+{
+ ///
+ ///
+ ///
+ /// Erich Eichinger
+ [TestFixture]
+ public class NamespaceParserRegistryTests
+ {
+ private class TestNamespaceParser : INamespaceParser
+ {
+ public void Init()
+ {
+ }
+
+ public IObjectDefinition ParseElement(XmlElement element, ParserContext parserContext)
+ {
+ throw new System.NotImplementedException();
+ }
+
+ public ObjectDefinitionHolder Decorate(XmlNode node, ObjectDefinitionHolder definition, ParserContext parserContext)
+ {
+ throw new System.NotImplementedException();
+ }
+ }
+
+#if !NET_1_0
+ ///
+ /// This test doesn't work on .NET 1.0 because there are no XmlResolvers for schema loading...
+ ///
+ [Test]
+ public void CanLoadSchemaImportingOtherSchemaByRelativePath()
+ {
+ string schemaLocation = GetAssemblyResource( this.GetType(), "NamespaceParserRegistryTests_TestSchema.xsd" );
+ NamespaceParserRegistry.RegisterParser(new TestNamespaceParser(), "http://www.example.com/brief", schemaLocation);
+ XmlReader vr = XmlUtils.CreateValidatingReader( new StringResource(
+ @"
+
+ ").InputStream, NamespaceParserRegistry.GetSchemas(), null);
+ ConfigXmlDocument newDoc = new ConfigXmlDocument();
+ newDoc.Load(vr);
+ }
+#endif
+ private string GetAssemblyResource( Type hint, string name)
+ {
+ return "assembly://" + hint.Assembly.FullName.Split(',')[0].Trim() + "/" + hint.Namespace + "/" + name;
+ }
+ }
+}
\ No newline at end of file
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Xml/NamespaceParserRegistryTests_TestSchema.xsd b/test/Spring/Spring.Core.Tests/Objects/Factory/Xml/NamespaceParserRegistryTests_TestSchema.xsd
new file mode 100644
index 00000000..3eb08fdb
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Xml/NamespaceParserRegistryTests_TestSchema.xsd
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/test/Spring/Spring.Core.Tests/Objects/Factory/Xml/NamespaceParserRegistryTests_TestSchema_2.xsd b/test/Spring/Spring.Core.Tests/Objects/Factory/Xml/NamespaceParserRegistryTests_TestSchema_2.xsd
new file mode 100644
index 00000000..650f07f7
--- /dev/null
+++ b/test/Spring/Spring.Core.Tests/Objects/Factory/Xml/NamespaceParserRegistryTests_TestSchema_2.xsd
@@ -0,0 +1,11 @@
+
+
+
+
+
+
+
+
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 204c0622..9e69e8e6 100644
--- a/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2003.csproj
+++ b/test/Spring/Spring.Core.Tests/Spring.Core.Tests.2003.csproj
@@ -1592,6 +1592,19 @@
SubType = "Code"
BuildAction = "Compile"
/>
+
+
+
+
+
@@ -748,6 +750,8 @@
testobject.xsd
+
+
@@ -889,4 +893,4 @@
xcopy "$(ProjectDir)Data" ..\..\..\..\build\VS.Net.2008\Spring.Core.Tests\$(ConfigurationName)\ /y /s /q /d
xcopy "$(ProjectDir)$(TargetFileName).config" ..\..\..\..\build\VS.Net.2008\Spring.Core.Tests\$(ConfigurationName)\ /y /s /q
-
+
\ No newline at end of file