2016-08-03 10:59:49 +00:00
|
|
|
//---------------------------------------------------------------------
|
|
|
|
// <copyright file="MetadataArtifactLoaderResource.cs" company="Microsoft">
|
|
|
|
// Copyright (c) Microsoft Corporation. All rights reserved.
|
|
|
|
// </copyright>
|
|
|
|
//
|
2017-08-21 15:34:15 +00:00
|
|
|
// @owner Microsoft
|
|
|
|
// @backupOwner Microsoft
|
2016-08-03 10:59:49 +00:00
|
|
|
//---------------------------------------------------------------------
|
|
|
|
|
|
|
|
namespace System.Data.Metadata.Edm
|
|
|
|
{
|
|
|
|
using System.Collections.Generic;
|
|
|
|
using System.Data.EntityModel.SchemaObjectModel;
|
|
|
|
using System.Diagnostics;
|
|
|
|
using System.IO;
|
|
|
|
using System.Reflection;
|
|
|
|
using System.Xml;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// This class represents one resource item to be loaded from an assembly.
|
|
|
|
/// </summary>
|
|
|
|
internal class MetadataArtifactLoaderResource : MetadataArtifactLoader, IComparable
|
|
|
|
{
|
|
|
|
private readonly bool _alreadyLoaded = false;
|
|
|
|
private readonly Assembly _assembly;
|
|
|
|
private readonly string _resourceName;
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Constructor - loads the resource stream
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="path">The path to the resource to load</param>
|
|
|
|
/// <param name="uriRegistry">The global registry of URIs</param>
|
|
|
|
internal MetadataArtifactLoaderResource(Assembly assembly, string resourceName, ICollection<string> uriRegistry)
|
|
|
|
{
|
|
|
|
Debug.Assert(assembly != null);
|
|
|
|
Debug.Assert(resourceName != null);
|
|
|
|
|
|
|
|
_assembly = assembly;
|
|
|
|
_resourceName = resourceName;
|
|
|
|
|
|
|
|
string tempPath = MetadataArtifactLoaderCompositeResource.CreateResPath(_assembly, _resourceName);
|
|
|
|
_alreadyLoaded = uriRegistry.Contains(tempPath);
|
|
|
|
if (!_alreadyLoaded)
|
|
|
|
{
|
|
|
|
uriRegistry.Add(tempPath);
|
|
|
|
|
|
|
|
// '_alreadyLoaded' is not set because while we would like to prevent
|
|
|
|
// other instances of MetadataArtifactLoaderFile that wrap the same
|
|
|
|
// _path from being added to the list of paths/readers, we do want to
|
|
|
|
// include this particular instance.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
public override string Path
|
|
|
|
{
|
|
|
|
get
|
|
|
|
{
|
|
|
|
return MetadataArtifactLoaderCompositeResource.CreateResPath(_assembly, _resourceName);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Implementation of IComparable.CompareTo()
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="obj">The object to compare to</param>
|
|
|
|
/// <returns>0 if the loaders are "equal" (i.e., have the same _path value)</returns>
|
|
|
|
public int CompareTo(object obj)
|
|
|
|
{
|
|
|
|
MetadataArtifactLoaderResource loader = obj as MetadataArtifactLoaderResource;
|
|
|
|
if (loader != null)
|
|
|
|
{
|
|
|
|
return string.Compare(Path, loader.Path, StringComparison.OrdinalIgnoreCase);
|
|
|
|
}
|
|
|
|
|
|
|
|
Debug.Assert(false, "object is not a MetadataArtifactLoaderResource");
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Equals() returns true if the objects have the same _path value
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="obj">The object to compare to</param>
|
|
|
|
/// <returns>true if the objects have the same _path value</returns>
|
|
|
|
public override bool Equals(object obj)
|
|
|
|
{
|
|
|
|
return this.CompareTo(obj) == 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// GetHashCode override that defers the result to the _path member variable.
|
|
|
|
/// </summary>
|
|
|
|
/// <returns></returns>
|
|
|
|
public override int GetHashCode()
|
|
|
|
{
|
|
|
|
return Path.GetHashCode();
|
|
|
|
}
|
|
|
|
|
|
|
|
public override void CollectFilePermissionPaths(List<string> paths, DataSpace spaceToGet)
|
|
|
|
{
|
|
|
|
// does not apply
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Get paths to artifacts for a specific DataSpace.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="spaceToGet">The DataSpace for the artifacts of interest</param>
|
|
|
|
/// <returns>A List of strings identifying paths to all artifacts for a specific DataSpace</returns>
|
|
|
|
public override List<string> GetPaths(DataSpace spaceToGet)
|
|
|
|
{
|
|
|
|
List<string> list = new List<string>();
|
|
|
|
if (!_alreadyLoaded && MetadataArtifactLoader.IsArtifactOfDataSpace(Path, spaceToGet))
|
|
|
|
{
|
|
|
|
list.Add(Path);
|
|
|
|
}
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Get paths to all artifacts
|
|
|
|
/// </summary>
|
|
|
|
/// <returns>A List of strings identifying paths to all resources</returns>
|
|
|
|
public override List<string> GetPaths()
|
|
|
|
{
|
|
|
|
List<string> list = new List<string>();
|
|
|
|
if (!_alreadyLoaded)
|
|
|
|
{
|
|
|
|
list.Add(Path);
|
|
|
|
}
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Create and return an XmlReader around the resource represented by this instance.
|
|
|
|
/// </summary>
|
|
|
|
/// <returns>A List of XmlReaders for all resources</returns>
|
|
|
|
public override List<XmlReader> GetReaders(Dictionary<MetadataArtifactLoader, XmlReader> sourceDictionary)
|
|
|
|
{
|
|
|
|
List<XmlReader> list = new List<XmlReader>();
|
|
|
|
if (!_alreadyLoaded)
|
|
|
|
{
|
|
|
|
|
|
|
|
XmlReader reader = CreateReader();
|
|
|
|
list.Add(reader);
|
|
|
|
|
|
|
|
if (sourceDictionary != null)
|
|
|
|
{
|
|
|
|
sourceDictionary.Add(this, reader);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
private XmlReader CreateReader()
|
|
|
|
{
|
|
|
|
|
|
|
|
Stream stream = LoadResource();
|
|
|
|
|
|
|
|
XmlReaderSettings readerSettings = Schema.CreateEdmStandardXmlReaderSettings();
|
|
|
|
// close the stream when the xmlreader is closed
|
|
|
|
// now the reader owns the stream
|
|
|
|
readerSettings.CloseInput = true;
|
|
|
|
|
|
|
|
// we know that we aren't reading a fragment
|
|
|
|
readerSettings.ConformanceLevel = ConformanceLevel.Document;
|
|
|
|
XmlReader reader = XmlReader.Create(stream, readerSettings);
|
|
|
|
// cannot set the base URI because res:// URIs cause the schema parser
|
|
|
|
// to choke
|
|
|
|
|
|
|
|
return reader;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// Create and return an XmlReader around the resource represented by this instance
|
|
|
|
/// if it is of the requested DataSpace type.
|
|
|
|
/// </summary>
|
|
|
|
/// <param name="spaceToGet">The DataSpace corresponding to the requested artifacts</param>
|
|
|
|
/// <returns>A List of XmlReader objects</returns>
|
|
|
|
public override List<XmlReader> CreateReaders(DataSpace spaceToGet)
|
|
|
|
{
|
|
|
|
List<XmlReader> list = new List<XmlReader>();
|
|
|
|
if (!_alreadyLoaded)
|
|
|
|
{
|
|
|
|
if (MetadataArtifactLoader.IsArtifactOfDataSpace(Path, spaceToGet))
|
|
|
|
{
|
|
|
|
XmlReader reader = CreateReader();
|
|
|
|
list.Add(reader);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return list;
|
|
|
|
}
|
|
|
|
|
|
|
|
/// <summary>
|
|
|
|
/// This method parses the path to the resource and attempts to load it.
|
|
|
|
/// The method also accounts for the wildcard assembly name.
|
|
|
|
/// </summary>
|
|
|
|
private Stream LoadResource()
|
|
|
|
{
|
|
|
|
Stream resourceStream;
|
|
|
|
if (TryCreateResourceStream(out resourceStream))
|
|
|
|
{
|
|
|
|
return resourceStream;
|
|
|
|
}
|
|
|
|
throw EntityUtil.Metadata(System.Data.Entity.Strings.UnableToLoadResource);
|
|
|
|
}
|
|
|
|
|
|
|
|
private bool TryCreateResourceStream(out Stream resourceStream)
|
|
|
|
{
|
|
|
|
resourceStream = _assembly.GetManifestResourceStream(_resourceName);
|
|
|
|
return resourceStream != null;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|