using System;
using System.IO;
using System.Net;
using System.Reflection;
using System.Web;
using System.Xml;
using System.Xml.Schema;
using NUnit.Framework;
using Spring.Core.IO;
namespace Spring{
/// <summary>
/// Supports obtaining embedded resources from assembly.
/// </summary>
/// <remarks>
/// <para>
/// The first <c>context</c> argument is always the namespace scope to be used for resolving resource names.
/// </para>
/// <para>
/// Upon first usage, TestResourceLoader registers the "testres://" protocol prefix for loading embedded resources.
/// A testres:// Url must be of the form "testres://./<context-typename>#<ext" - <see cref="GetStream"/>.
/// </para>
/// </remarks>
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()
{ }
/// <summary>
/// Returns an Uri of the form "testres://./resourcname" that may be passed into <see cref="WebRequest.Create(string)"/> etc.
/// </summary>
/// <param name="context"></param>
/// <param name="ext"></param>
/// <returns></returns>
public static Uri GetUri(object context, string ext)
{
string resname = context.GetType().AssemblyQualifiedName + "#" + ext;
Uri uri = new Uri("testres://inline/" + 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 XmlDocument GetXmlValidated(object context, string ext, params IResource[] schemaResources)
{
using (Stream stm = GetStream(context, ext))
{
#if !NET_2_0
XmlValidatingReader validatingReader = new XmlValidatingReader(stm, XmlNodeType.Document, null);
validatingReader.ValidationType = ValidationType.Schema;
XmlSchemaCollection schemas = validatingReader.Schemas;
#else
XmlReaderSettings settings = new XmlReaderSettings();
settings.ValidationType = ValidationType.Schema;
XmlSchemaSet schemas = settings.Schemas;
#endif
foreach (IResource schemaResource in schemaResources)
{
XmlDocument schemaDoc = new XmlDocument();
using (Stream inputStream = schemaResource.InputStream)
{
schemaDoc.Load(inputStream);
}
XmlElement root = schemaDoc.DocumentElement;
string targetNamespace = root.GetAttribute("targetNamespace", string.Empty);
schemas.Add(targetNamespace, new XmlNodeReader(schemaDoc));
}
#if NET_2_0
XmlReader validatingReader = XmlReader.Create(stm, settings);
#endif
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.Load(validatingReader);
validatingReader.Close();
return xmlDoc;
}
}
/// <summary>
/// Returns an embedded assembly resource, who's name is constructed from the given parameters as
/// <c>context.GetType().FullName + ext</c>
/// </summary>
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;
}
/// <summary>
/// Exports a resource obtained via <see cref="GetStream"/> to the specified destination.
/// </summary>
public static FileInfo ExportResource(object context, string ext, FileInfo destination)
{
Stream istm = GetStream(context, ext);
using(istm)
{
FileStream ostm = destination.OpenWrite();
using (ostm)
{
byte[] buffer = new byte[2048];
int bytesRead = istm.Read(buffer, 0, buffer.Length);
while (bytesRead > 0)
{
ostm.Write(buffer, 0, bytesRead);
bytesRead = istm.Read(buffer, 0, buffer.Length);
}
ostm.Flush();
ostm.Close();
}
istm.Close();
}
return destination;
}
/// <summary>
/// returns an "assembly://" uri for the specified manifest resource, scoped by the namespace of the specified type.
/// ("assembly://hint.assemblyname_without_version/hint.Namespace/name")
/// </summary>
/// <see cref="Assembly.GetManifestResourceStream(Type,string)"/>
public static string GetAssemblyResourceUri(Type hint, string name)
{
return "assembly://" + hint.Assembly.FullName.Split(',')[0].Trim() + "/" + hint.Namespace + ((name.IndexOf('/')>-1)?".":"/") + name;
}
/// <summary>
/// returns an "assembly://" uri for the specified manifest resource, scoped by the namespace of the specified instance's type.
/// ("assembly://hint.assemblyname_without_version/hint.Namespace/name")
/// </summary>
/// <see cref="Assembly.GetManifestResourceStream(Type,string)"/>
public static string GetAssemblyResourceUri(object hint, string name)
{
Type hintType = hint.GetType();
return GetAssemblyResourceUri(hintType, name);
}
}
}
|