Updates referencesource to .NET 4.7
[mono.git] / mcs / class / referencesource / System.Data.Entity / System / Data / Metadata / MetadataArtifactLoaderResource.cs
1 //---------------------------------------------------------------------
2 // <copyright file="MetadataArtifactLoaderResource.cs" company="Microsoft">
3 //      Copyright (c) Microsoft Corporation.  All rights reserved.
4 // </copyright>
5 //
6 // @owner       Microsoft
7 // @backupOwner Microsoft
8 //---------------------------------------------------------------------
9
10 namespace System.Data.Metadata.Edm
11 {
12     using System.Collections.Generic;
13     using System.Data.EntityModel.SchemaObjectModel;
14     using System.Diagnostics;
15     using System.IO;
16     using System.Reflection;
17     using System.Xml;
18
19     /// <summary>
20     /// This class represents one resource item to be loaded from an assembly.
21     /// </summary>
22     internal class MetadataArtifactLoaderResource : MetadataArtifactLoader, IComparable
23     {
24         private readonly bool _alreadyLoaded = false;
25         private readonly Assembly _assembly;
26         private readonly string _resourceName;
27
28         /// <summary>
29         /// Constructor - loads the resource stream
30         /// </summary>
31         /// <param name="path">The path to the resource to load</param>
32         /// <param name="uriRegistry">The global registry of URIs</param>
33         internal MetadataArtifactLoaderResource(Assembly assembly, string resourceName, ICollection<string> uriRegistry)
34         {
35             Debug.Assert(assembly != null);
36             Debug.Assert(resourceName != null);
37
38             _assembly = assembly;
39             _resourceName = resourceName;
40
41             string tempPath = MetadataArtifactLoaderCompositeResource.CreateResPath(_assembly, _resourceName);
42             _alreadyLoaded = uriRegistry.Contains(tempPath);
43             if (!_alreadyLoaded)
44             {
45                 uriRegistry.Add(tempPath);
46
47                 // '_alreadyLoaded' is not set because while we would like to prevent
48                 // other instances of MetadataArtifactLoaderFile that wrap the same
49                 // _path from being added to the list of paths/readers, we do want to
50                 // include this particular instance.
51             }
52         }
53
54         public override string Path
55         {
56             get 
57             {
58                 return MetadataArtifactLoaderCompositeResource.CreateResPath(_assembly, _resourceName);
59             }
60         }
61
62         /// <summary>
63         /// Implementation of IComparable.CompareTo()
64         /// </summary>
65         /// <param name="obj">The object to compare to</param>
66         /// <returns>0 if the loaders are "equal" (i.e., have the same _path value)</returns>
67         public int CompareTo(object obj)
68         {
69             MetadataArtifactLoaderResource loader = obj as MetadataArtifactLoaderResource;
70             if (loader != null)
71             {
72                 return string.Compare(Path, loader.Path, StringComparison.OrdinalIgnoreCase);
73             }
74
75             Debug.Assert(false, "object is not a MetadataArtifactLoaderResource");
76             return -1;
77         }
78
79         /// <summary>
80         /// Equals() returns true if the objects have the same _path value
81         /// </summary>
82         /// <param name="obj">The object to compare to</param>
83         /// <returns>true if the objects have the same _path value</returns>
84         public override bool Equals(object obj)
85         {
86             return this.CompareTo(obj) == 0;
87         }
88
89         /// <summary>
90         /// GetHashCode override that defers the result to the _path member variable.
91         /// </summary>
92         /// <returns></returns>
93         public override int GetHashCode()
94         {
95             return Path.GetHashCode();
96         }
97
98         public override void CollectFilePermissionPaths(List<string> paths, DataSpace spaceToGet)
99         {
100             // does not apply
101         }
102
103         /// <summary>
104         /// Get paths to artifacts for a specific DataSpace.
105         /// </summary>
106         /// <param name="spaceToGet">The DataSpace for the artifacts of interest</param>
107         /// <returns>A List of strings identifying paths to all artifacts for a specific DataSpace</returns>
108         public override List<string> GetPaths(DataSpace spaceToGet)
109         {
110             List<string> list = new List<string>();
111             if (!_alreadyLoaded && MetadataArtifactLoader.IsArtifactOfDataSpace(Path, spaceToGet))
112             {
113                 list.Add(Path);
114             }
115             return list;
116         }
117
118         /// <summary>
119         /// Get paths to all artifacts
120         /// </summary>
121         /// <returns>A List of strings identifying paths to all resources</returns>
122         public override List<string> GetPaths()
123         {
124             List<string> list = new List<string>();
125             if (!_alreadyLoaded)
126             {
127                 list.Add(Path);
128             }
129             return list;
130         }
131
132         /// <summary>
133         /// Create and return an XmlReader around the resource represented by this instance.
134         /// </summary>
135         /// <returns>A List of XmlReaders for all resources</returns>
136         public override List<XmlReader> GetReaders(Dictionary<MetadataArtifactLoader, XmlReader> sourceDictionary)
137         {
138             List<XmlReader> list = new List<XmlReader>();
139             if (!_alreadyLoaded)
140             {
141
142                 XmlReader reader = CreateReader();
143                 list.Add(reader);
144
145                 if (sourceDictionary != null)
146                 {
147                     sourceDictionary.Add(this, reader);
148                 }
149             }
150             return list;
151         }
152
153         private XmlReader CreateReader()
154         {
155
156             Stream stream = LoadResource();
157
158             XmlReaderSettings readerSettings = Schema.CreateEdmStandardXmlReaderSettings();
159             // close the stream when the xmlreader is closed
160             // now the reader owns the stream
161             readerSettings.CloseInput = true;
162
163             // we know that we aren't reading a fragment
164             readerSettings.ConformanceLevel = ConformanceLevel.Document;
165             XmlReader reader = XmlReader.Create(stream, readerSettings);
166             // cannot set the base URI because res:// URIs cause the schema parser
167             // to choke
168
169             return reader;
170         }
171
172         /// <summary>
173         /// Create and return an XmlReader around the resource represented by this instance
174         /// if it is of the requested DataSpace type.
175         /// </summary>
176         /// <param name="spaceToGet">The DataSpace corresponding to the requested artifacts</param>
177         /// <returns>A List of XmlReader objects</returns>
178         public override List<XmlReader> CreateReaders(DataSpace spaceToGet)
179         {
180             List<XmlReader> list = new List<XmlReader>();
181             if (!_alreadyLoaded)
182             {
183                 if (MetadataArtifactLoader.IsArtifactOfDataSpace(Path, spaceToGet))
184                 {
185                     XmlReader reader = CreateReader();
186                     list.Add(reader);
187                 }
188             }
189             return list;
190         }
191
192         /// <summary>
193         /// This method parses the path to the resource and attempts to load it.
194         /// The method also accounts for the wildcard assembly name.
195         /// </summary>
196         private Stream LoadResource()
197         {
198             Stream resourceStream;
199             if (TryCreateResourceStream(out resourceStream))
200             {
201                 return resourceStream;
202             }
203             throw EntityUtil.Metadata(System.Data.Entity.Strings.UnableToLoadResource);
204         }
205
206         private bool TryCreateResourceStream(out Stream resourceStream)
207         {
208             resourceStream = _assembly.GetManifestResourceStream(_resourceName);
209             return resourceStream != null;
210         }
211     }
212 }