resolved SPRNET-1079

This commit is contained in:
eeichinger
2008-11-04 03:26:57 +00:00
parent 3bc38fb610
commit 916103202d
9 changed files with 243 additions and 27 deletions

View File

@@ -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
/// <summary>
/// Returns the <see cref="System.Uri"/> handle for this resource.
/// </summary>
@@ -222,7 +225,19 @@ namespace Spring.Core.IO
Description + " cannot be resolved to a Uri.");
}
}
#else
/// <summary>
/// Returns the <see cref="System.Uri"/> handle for this resource.
/// </summary>
/// <seealso cref="Spring.Core.IO.IResource.Uri"/>
public virtual Uri Uri
{
get
{
return new Uri(resourceName);
}
}
#endif
/// <summary>
/// Returns a <see cref="System.IO.FileInfo"/> handle for this resource.
/// </summary>

View File

@@ -248,6 +248,19 @@ namespace Spring.Core.IO
}
}
#if NET_2_0
/// <summary>
/// Returns the <see cref="System.Uri"/> handle for this resource.
/// </summary>
/// <seealso cref="Spring.Core.IO.IResource.Uri"/>
public override Uri Uri
{
get
{
return new Uri(_fullResourceName);
}
}
#endif
#endregion
/// <summary>

View File

@@ -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
/// <summary>
/// Allows to create any arbitrary Url format
/// </summary>
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)});

View File

@@ -47,6 +47,26 @@ namespace Spring.Objects.Factory.Xml
/// <author>Aleksandar Seovic</author>
public class NamespaceParserRegistry
{
/// <summary>
/// Resolves xml entities by using the <see cref="IResourceLoader"/> infrastructure.
/// </summary>
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 );
}
}
/// <summary>
/// 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
/// </summary>
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);
}
/// <summary>
@@ -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);
}

View File

@@ -0,0 +1,82 @@
#region License
/*
* Copyright <20> 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
{
/// <summary>
///
/// </summary>
/// <author>Erich Eichinger</author>
[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
/// <summary>
/// This test doesn't work on .NET 1.0 because there are no XmlResolvers for schema loading...
/// </summary>
[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(
@"<?xml version='1.0' encoding='UTF-8' ?>
<brief class='foo' />
").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;
}
}
}

View File

@@ -0,0 +1,20 @@
<xsd:schema targetNamespace="http://www.example.com/brief"
xmlns:brief="http://www.example.com/brief"
xmlns:ex="http://www.example.com/common"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.example.com/common" schemaLocation="NamespaceParserRegistryTests_TestSchema_2.xsd"/>
<xsd:element name="brief">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="kopf" type="xsd:string"/>
<xsd:element name="inhalt" type="xsd:string"/>
</xsd:sequence>
<xsd:attributeGroup ref="ex:CommonAttributes"/>
</xsd:complexType>
</xsd:element>
</xsd:schema>

View File

@@ -0,0 +1,11 @@
<xsd:schema targetNamespace="http://www.example.com/common"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:attributeGroup name="CommonAttributes">
<xsd:attribute name="class" type="xsd:NMTOKEN" use="optional"/>
<xsd:attribute name="id" type="xsd:ID" use="required"/>
</xsd:attributeGroup>
</xsd:schema>

View File

@@ -1592,6 +1592,19 @@
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Objects\Factory\Xml\NamespaceParserRegistryTests.cs"
SubType = "Code"
BuildAction = "Compile"
/>
<File
RelPath = "Objects\Factory\Xml\NamespaceParserRegistryTests_TestSchema.xsd"
BuildAction = "EmbeddedResource"
/>
<File
RelPath = "Objects\Factory\Xml\NamespaceParserRegistryTests_TestSchema_2.xsd"
BuildAction = "EmbeddedResource"
/>
<File
RelPath = "Objects\Factory\Xml\NullAppender.cs"
SubType = "Code"

View File

@@ -329,7 +329,9 @@
<Compile Include="Objects\Factory\Support\ObjectDefinitionBuilderTests.cs" />
<Compile Include="Objects\Factory\Xml\ArrayCtorDependencyObject.cs" />
<Compile Include="Objects\Factory\Xml\LocaleTests.cs" />
<Compile Include="Objects\Factory\Xml\NamespaceParserRegistryTests.cs" />
<Compile Include="Objects\Factory\Xml\ObjectFactorySectionHandlerTests.cs" />
<Compile Include="Objects\Factory\Xml\ObjectNameGenerationTests.cs" />
<Compile Include="Objects\Factory\Xml\SiimpleCtorWiringTests.cs" />
<Compile Include="Objects\LazyTestObject.cs" />
<Compile Include="Objects\Support\AbstractSharedStateFactoryTests.cs" />
@@ -748,6 +750,8 @@
<None Include="Context\Support\testobject.xsx">
<DependentUpon>testobject.xsd</DependentUpon>
</None>
<EmbeddedResource Include="Objects\Factory\Xml\NamespaceParserRegistryTests_TestSchema.xsd" />
<EmbeddedResource Include="Objects\Factory\Xml\NamespaceParserRegistryTests_TestSchema_2.xsd" />
<None Include="Spring.Core.Tests.build" />
<EmbeddedResource Include="Context\Support\contextB.xml" />
<EmbeddedResource Include="Context\Support\contextC.xml" />
@@ -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</PostBuildEvent>
</PropertyGroup>
</Project>
</Project>