Update mcs/class/System.Core/System/TimeZoneInfo.cs
[mono.git] / mcs / class / IKVM.Reflection / Reader / AssemblyReader.cs
1 /*
2   Copyright (C) 2009 Jeroen Frijters
3
4   This software is provided 'as-is', without any express or implied
5   warranty.  In no event will the authors be held liable for any damages
6   arising from the use of this software.
7
8   Permission is granted to anyone to use this software for any purpose,
9   including commercial applications, and to alter it and redistribute it
10   freely, subject to the following restrictions:
11
12   1. The origin of this software must not be misrepresented; you must not
13      claim that you wrote the original software. If you use this software
14      in a product, an acknowledgment in the product documentation would be
15      appreciated but is not required.
16   2. Altered source versions must be plainly marked as such, and must not be
17      misrepresented as being the original software.
18   3. This notice may not be removed or altered from any source distribution.
19
20   Jeroen Frijters
21   jeroen@frijters.net
22   
23 */
24 using System;
25 using System.Collections.Generic;
26 using System.Configuration.Assemblies;
27 using System.IO;
28 using IKVM.Reflection.Metadata;
29
30 namespace IKVM.Reflection.Reader
31 {
32         sealed class AssemblyReader : Assembly
33         {
34                 private const int ContainsNoMetaData = 0x0001;
35                 private readonly string location;
36                 private readonly ModuleReader manifestModule;
37                 private readonly Module[] externalModules;
38
39                 internal AssemblyReader(string location, ModuleReader manifestModule)
40                         : base(manifestModule.universe)
41                 {
42                         this.location = location;
43                         this.manifestModule = manifestModule;
44                         externalModules = new Module[manifestModule.File.records.Length];
45                 }
46
47                 public override string Location
48                 {
49                         get { return location; }
50                 }
51
52                 public override AssemblyName GetName()
53                 {
54                         return GetNameImpl(ref manifestModule.AssemblyTable.records[0]);
55                 }
56
57                 private AssemblyName GetNameImpl(ref AssemblyTable.Record rec)
58                 {
59                         AssemblyName name = new AssemblyName();
60                         name.Name = manifestModule.GetString(rec.Name);
61                         name.Version = new Version(rec.MajorVersion, rec.MinorVersion, rec.BuildNumber, rec.RevisionNumber);
62                         if (rec.PublicKey != 0)
63                         {
64                                 name.SetPublicKey(manifestModule.GetBlobCopy(rec.PublicKey));
65                         }
66                         else
67                         {
68                                 name.SetPublicKey(Empty<byte>.Array);
69                         }
70                         if (rec.Culture != 0)
71                         {
72                                 name.Culture = manifestModule.GetString(rec.Culture);
73                         }
74                         else
75                         {
76                                 name.Culture = "";
77                         }
78                         name.HashAlgorithm = (AssemblyHashAlgorithm)rec.HashAlgId;
79                         name.CodeBase = this.CodeBase;
80                         name.RawFlags = (AssemblyNameFlags)rec.Flags;
81                         return name;
82                 }
83
84                 public override Type[] GetTypes()
85                 {
86                         if (externalModules.Length == 0)
87                         {
88                                 return manifestModule.GetTypes();
89                         }
90
91                         List<Type> list = new List<Type>();
92                         foreach (Module module in GetModules(false))
93                         {
94                                 list.AddRange(module.GetTypes());
95                         }
96                         return list.ToArray();
97                 }
98
99                 internal override Type FindType(TypeName typeName)
100                 {
101                         Type type = manifestModule.FindType(typeName);
102                         for (int i = 0; type == null && i < externalModules.Length; i++)
103                         {
104                                 if ((manifestModule.File.records[i].Flags & ContainsNoMetaData) == 0)
105                                 {
106                                         type = GetModule(i).FindType(typeName);
107                                 }
108                         }
109                         return type;
110                 }
111
112                 internal override Type FindTypeIgnoreCase(TypeName lowerCaseName)
113                 {
114                         Type type = manifestModule.FindTypeIgnoreCase(lowerCaseName);
115                         for (int i = 0; type == null && i < externalModules.Length; i++)
116                         {
117                                 if ((manifestModule.File.records[i].Flags & ContainsNoMetaData) == 0)
118                                 {
119                                         type = GetModule(i).FindTypeIgnoreCase(lowerCaseName);
120                                 }
121                         }
122                         return type;
123                 }
124
125                 public override string ImageRuntimeVersion
126                 {
127                         get { return manifestModule.__ImageRuntimeVersion; }
128                 }
129
130                 public override Module ManifestModule
131                 {
132                         get { return manifestModule; }
133                 }
134
135                 public override Module[] GetLoadedModules(bool getResourceModules)
136                 {
137                         List<Module> list = new List<Module>();
138                         list.Add(manifestModule);
139                         foreach (Module m in externalModules)
140                         {
141                                 if (m != null)
142                                 {
143                                         list.Add(m);
144                                 }
145                         }
146                         return list.ToArray();
147                 }
148
149                 public override Module[] GetModules(bool getResourceModules)
150                 {
151                         if (externalModules.Length == 0)
152                         {
153                                 return new Module[] { manifestModule };
154                         }
155                         else
156                         {
157                                 List<Module> list = new List<Module>();
158                                 list.Add(manifestModule);
159                                 for (int i = 0; i < manifestModule.File.records.Length; i++)
160                                 {
161                                         if (getResourceModules || (manifestModule.File.records[i].Flags & ContainsNoMetaData) == 0)
162                                         {
163                                                 list.Add(GetModule(i));
164                                         }
165                                 }
166                                 return list.ToArray();
167                         }
168                 }
169
170                 public override Module GetModule(string name)
171                 {
172                         if (name.Equals(manifestModule.ScopeName, StringComparison.InvariantCultureIgnoreCase))
173                         {
174                                 return manifestModule;
175                         }
176                         int index = GetModuleIndex(name);
177                         if (index != -1)
178                         {
179                                 return GetModule(index);
180                         }
181                         return null;
182                 }
183
184                 private int GetModuleIndex(string name)
185                 {
186                         for (int i = 0; i < manifestModule.File.records.Length; i++)
187                         {
188                                 if (name.Equals(manifestModule.GetString(manifestModule.File.records[i].Name), StringComparison.InvariantCultureIgnoreCase))
189                                 {
190                                         return i;
191                                 }
192                         }
193                         return -1;
194                 }
195
196                 private Module GetModule(int index)
197                 {
198                         if (externalModules[index] != null)
199                         {
200                                 return externalModules[index];
201                         }
202                         // TODO add ModuleResolve event
203                         string location = Path.Combine(Path.GetDirectoryName(this.location), manifestModule.GetString(manifestModule.File.records[index].Name));
204                         return LoadModule(index, null, location);
205                 }
206
207                 private Module LoadModule(int index, byte[] rawModule, string location)
208                 {
209                         if ((manifestModule.File.records[index].Flags & ContainsNoMetaData) != 0)
210                         {
211                                 return externalModules[index] = new ResourceModule(manifestModule, index, location);
212                         }
213                         else
214                         {
215                                 if (rawModule == null)
216                                 {
217                                         rawModule = File.ReadAllBytes(location);
218                                 }
219                                 return externalModules[index] = new ModuleReader(this, manifestModule.universe, new MemoryStream(rawModule), location);
220                         }
221                 }
222
223                 public override Module LoadModule(string moduleName, byte[] rawModule)
224                 {
225                         int index = GetModuleIndex(moduleName);
226                         if (index == -1)
227                         {
228                                 throw new ArgumentException();
229                         }
230                         if (externalModules[index] != null)
231                         {
232                                 return externalModules[index];
233                         }
234                         return LoadModule(index, rawModule, null);
235                 }
236
237                 public override MethodInfo EntryPoint
238                 {
239                         get { return manifestModule.GetEntryPoint(); }
240                 }
241
242                 public override string[] GetManifestResourceNames()
243                 {
244                         return manifestModule.GetManifestResourceNames();
245                 }
246
247                 public override ManifestResourceInfo GetManifestResourceInfo(string resourceName)
248                 {
249                         return manifestModule.GetManifestResourceInfo(resourceName);
250                 }
251
252                 public override Stream GetManifestResourceStream(string resourceName)
253                 {
254                         return manifestModule.GetManifestResourceStream(resourceName);
255                 }
256
257                 public override AssemblyName[] GetReferencedAssemblies()
258                 {
259                         return manifestModule.__GetReferencedAssemblies();
260                 }
261
262                 public override AssemblyNameFlags __AssemblyFlags
263                 {
264                         get { return (AssemblyNameFlags)manifestModule.AssemblyTable.records[0].Flags; }
265                 }
266
267                 internal string Name
268                 {
269                         get { return manifestModule.GetString(manifestModule.AssemblyTable.records[0].Name); }
270                 }
271
272                 internal override IList<CustomAttributeData> GetCustomAttributesData(Type attributeType)
273                 {
274                         return CustomAttributeData.GetCustomAttributesImpl(null, manifestModule, 0x20000001, attributeType) ?? CustomAttributeData.EmptyList;
275                 }
276         }
277 }