2008-03-14 Martin Baulig <martin@ximian.com>
[mono.git] / mcs / class / corlib / System.Reflection / Module.cs
1 //
2 // System.Reflection/Module.cs
3 //
4 // Author:
5 //   Paolo Molaro (lupus@ximian.com)
6 //
7 // (C) 2001 Ximian, Inc.  http://www.ximian.com
8 // Copyright (C) 2004-2005 Novell, Inc (http://www.novell.com)
9 //
10 // Permission is hereby granted, free of charge, to any person obtaining
11 // a copy of this software and associated documentation files (the
12 // "Software"), to deal in the Software without restriction, including
13 // without limitation the rights to use, copy, modify, merge, publish,
14 // distribute, sublicense, and/or sell copies of the Software, and to
15 // permit persons to whom the Software is furnished to do so, subject to
16 // the following conditions:
17 // 
18 // The above copyright notice and this permission notice shall be
19 // included in all copies or substantial portions of the Software.
20 // 
21 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28 //
29
30 using System.Runtime.Serialization;
31 using System.Security.Cryptography.X509Certificates;
32 using System.Runtime.InteropServices;
33 using System.Runtime.CompilerServices;
34 using System.Security;
35 using System.Security.Permissions;
36
37 namespace System.Reflection {
38
39         internal enum ResolveTokenError {
40                 OutOfRange,
41                 BadTable,
42                 Other
43         };
44
45 #if NET_2_0
46         [ComVisible (true)]
47         [ComDefaultInterfaceAttribute (typeof (_Module))]
48 #endif
49         [Serializable]
50         [ClassInterfaceAttribute (ClassInterfaceType.None)]
51         public class Module : ISerializable, ICustomAttributeProvider, _Module {
52         
53                 public static readonly TypeFilter FilterTypeName;
54                 public static readonly TypeFilter FilterTypeNameIgnoreCase;
55         
56                 private IntPtr _impl; /* a pointer to a MonoImage */
57                 internal Assembly assembly;
58                 internal string fqname;
59                 internal string name;
60                 internal string scopename;
61                 internal bool is_resource;
62                 internal int token;
63         
64                 const BindingFlags defaultBindingFlags = 
65                         BindingFlags.Public | BindingFlags.Static | BindingFlags.Instance;
66                 
67                 static Module () {
68                         FilterTypeName = new TypeFilter (filter_by_type_name);
69                         FilterTypeNameIgnoreCase = new TypeFilter (filter_by_type_name_ignore_case);
70                 }
71
72                 internal Module () {
73                 }
74
75                 public Assembly Assembly {
76                         get { return assembly; }
77                 }
78         
79                 public virtual string FullyQualifiedName {
80                         get {
81                                 if (SecurityManager.SecurityEnabled) {
82                                         new FileIOPermission (FileIOPermissionAccess.PathDiscovery, fqname).Demand ();
83                                 }
84                                 return fqname;
85                         }
86                 }
87
88                 // Note: we do not ask for PathDiscovery because no path is returned here.
89                 // However MS Fx requires it (see FDBK23572 for details).
90                 public string Name {
91                         get { return name; }
92                 }
93         
94                 public string ScopeName {
95                         get { return scopename; }
96                 }
97
98 #if NET_2_0
99                 public ModuleHandle ModuleHandle {
100                         get {
101                                 return new ModuleHandle (_impl);
102                         }
103                 }
104
105                 public extern int MetadataToken {
106                         [MethodImplAttribute (MethodImplOptions.InternalCall)]
107                         get;
108                 }
109
110                 public int MDStreamVersion {
111                         get {
112                                 if (_impl == IntPtr.Zero)
113                                         throw new NotSupportedException ();
114                                 return GetMDStreamVersion (_impl);
115                         }
116                 }
117
118                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
119                 internal static extern int GetMDStreamVersion (IntPtr module_handle);
120 #endif
121         
122                 public virtual Type[] FindTypes(TypeFilter filter, object filterCriteria) 
123                 {
124                         System.Collections.ArrayList filtered = new System.Collections.ArrayList ();
125                         Type[] types = GetTypes ();
126                         foreach (Type t in types)
127                                 if (filter (t, filterCriteria))
128                                         filtered.Add (t);
129                         return (Type[])filtered.ToArray (typeof(Type));
130                 }
131         
132                 public virtual object[] GetCustomAttributes(bool inherit) 
133                 {
134                         return MonoCustomAttrs.GetCustomAttributes (this, inherit);
135                 }
136         
137                 public virtual object[] GetCustomAttributes(Type attributeType, bool inherit) 
138                 {
139                         return MonoCustomAttrs.GetCustomAttributes (this, attributeType, inherit);
140                 }
141         
142                 public FieldInfo GetField (string name) 
143                 {
144                         if (IsResource ())
145                                 return null;
146
147                         Type globalType = GetGlobalType ();
148                         return (globalType != null) ? globalType.GetField (name, BindingFlags.Public | BindingFlags.Static) : null;
149                 }
150         
151                 public FieldInfo GetField (string name, BindingFlags bindingAttr) 
152                 {
153                         if (IsResource ())
154                                 return null;
155
156                         Type globalType = GetGlobalType ();
157                         return (globalType != null) ? globalType.GetField (name, bindingAttr) : null;
158                 }
159         
160                 public FieldInfo[] GetFields () 
161                 {
162                         if (IsResource ())
163                                 return new FieldInfo [0];
164
165                         Type globalType = GetGlobalType ();
166                         return (globalType != null) ? globalType.GetFields (BindingFlags.Public | BindingFlags.Static) : new FieldInfo [0];
167                 }
168         
169                 public MethodInfo GetMethod (string name) 
170                 {
171                         // Can't call the other overloads since they call Type.GetMethod () which does a null check on the 'types' array
172                         if (IsResource ())
173                                 return null;
174
175                         Type globalType = GetGlobalType ();
176                         return (globalType != null) ? globalType.GetMethod (name) : null;
177                 }
178         
179                 public MethodInfo GetMethod (string name, Type[] types) 
180                 {
181                         return GetMethodImpl (name, defaultBindingFlags, null, CallingConventions.Any, types, null);
182                 }
183         
184                 public MethodInfo GetMethod (string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) 
185                 {
186                         return GetMethodImpl (name, bindingAttr, binder, callConvention, types, modifiers);
187                 }
188         
189                 protected virtual MethodInfo GetMethodImpl (string name, BindingFlags bindingAttr, Binder binder, CallingConventions callConvention, Type[] types, ParameterModifier[] modifiers) 
190                 {
191                         if (IsResource ())
192                                 return null;
193
194                         Type globalType = GetGlobalType ();
195                         return (globalType != null) ? globalType.GetMethod (name, bindingAttr, binder, callConvention, types, modifiers) : null;
196                 }
197         
198                 public MethodInfo[] GetMethods () 
199                 {
200                         if (IsResource ())
201                                 return new MethodInfo [0];
202
203                         Type globalType = GetGlobalType ();
204                         return (globalType != null) ? globalType.GetMethods () : new MethodInfo [0];
205                 }
206
207 #if NET_2_0
208                 public MethodInfo[] GetMethods (BindingFlags bindingFlags) {
209                         if (IsResource ())
210                                 return new MethodInfo [0];
211
212                         Type globalType = GetGlobalType ();
213                         return (globalType != null) ? globalType.GetMethods (bindingFlags) : new MethodInfo [0];
214                 }
215
216                 public FieldInfo[] GetFields (BindingFlags bindingFlags)
217                 {
218                         if (IsResource ())
219                                 return new FieldInfo [0];
220
221                         Type globalType = GetGlobalType ();
222                         return (globalType != null) ? globalType.GetFields (bindingFlags) : new FieldInfo [0];
223                 }
224 #endif
225         
226                 [SecurityPermission (SecurityAction.LinkDemand, SerializationFormatter = true)]
227                 public virtual void GetObjectData (SerializationInfo info, StreamingContext context) 
228                 {
229                         if (info == null)
230                                 throw new ArgumentNullException ("info");
231
232                         UnitySerializationHolder.GetModuleData (this, info, context);
233                 }
234         
235                 public X509Certificate GetSignerCertificate ()
236                 {
237                         try {
238                                 return X509Certificate.CreateFromSignedFile (assembly.Location);
239                         }
240                         catch {
241                                 return null;
242                         }
243                 }
244
245 #if NET_2_0
246                 [ComVisible (true)]
247 #endif
248                 public virtual Type GetType(string className) 
249                 {
250                         return GetType (className, false, false);
251                 }
252
253 #if NET_2_0
254                 [ComVisible (true)]
255 #endif  
256                 public virtual Type GetType(string className, bool ignoreCase) 
257                 {
258                         return GetType (className, false, ignoreCase);
259                 }
260         
261 #if NET_2_0
262                 [ComVisible (true)]
263 #endif
264                 public virtual Type GetType(string className, bool throwOnError, bool ignoreCase) 
265                 {
266                         if (className == null)
267                                 throw new ArgumentNullException ("className");
268                         if (className == String.Empty)
269                                 throw new ArgumentException ("Type name can't be empty");
270                         return assembly.InternalGetType (this, className, throwOnError, ignoreCase);
271                 }
272
273                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
274                 private extern Type[] InternalGetTypes ();
275         
276                 public virtual Type[] GetTypes() 
277                 {
278                         return InternalGetTypes ();
279                 }
280         
281                 public virtual bool IsDefined (Type attributeType, bool inherit) 
282                 {
283                         return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
284                 }
285         
286                 public bool IsResource()
287                 {
288                         return is_resource;
289                 }
290         
291                 public override string ToString () 
292                 {
293                         return name;
294                 }
295
296                 internal Guid MvId {
297                         get {
298                                 return Mono_GetGuid (this);
299                         }
300                 }
301
302 #if NET_2_0
303                 public Guid ModuleVersionId {
304                         get {
305                                 return Mono_GetGuid (this);
306                         }
307                 }
308
309                 public void GetPEKind (out PortableExecutableKinds peKind, out ImageFileMachine machine) {
310                         ModuleHandle.GetPEKind (out peKind, out machine);
311                 }
312 #endif
313                 
314
315 #if NET_2_0
316                 private Exception resolve_token_exception (int metadataToken, ResolveTokenError error, string tokenType) {
317                         if (error == ResolveTokenError.OutOfRange)
318                                 return new ArgumentOutOfRangeException ("metadataToken", String.Format ("Token 0x{0:x} is not valid in the scope of module {1}", metadataToken, name));
319                         else
320                                 return new ArgumentException (String.Format ("Token 0x{0:x} is not a valid {1} token in the scope of module {2}", metadataToken, tokenType, name), "metadataToken");
321                 }
322
323                 private IntPtr[] ptrs_from_types (Type[] types) {
324                         if (types == null)
325                                 return null;
326                         else {
327                                 IntPtr[] res = new IntPtr [types.Length];
328                                 for (int i = 0; i < types.Length; ++i) {
329                                         if (types [i] == null)
330                                                 throw new ArgumentException ();
331                                         res [i] = types [i].TypeHandle.Value;
332                                 }
333                                 return res;
334                         }
335                 }
336
337                 public FieldInfo ResolveField (int metadataToken) {
338                         return ResolveField (metadataToken, null, null);
339                 }
340
341                 public FieldInfo ResolveField (int metadataToken, Type [] genericTypeArguments, Type [] genericMethodArguments) {
342                         ResolveTokenError error;
343
344                         IntPtr handle = ResolveFieldToken (_impl, metadataToken, ptrs_from_types (genericTypeArguments), ptrs_from_types (genericMethodArguments), out error);
345                         if (handle == IntPtr.Zero)
346                                 throw resolve_token_exception (metadataToken, error, "Field");
347                         else
348                                 return FieldInfo.GetFieldFromHandle (new RuntimeFieldHandle (handle));
349                 }
350
351                 public MemberInfo ResolveMember (int metadataToken) {
352                         return ResolveMember (metadataToken, null, null);
353                 }
354
355                 public MemberInfo ResolveMember (int metadataToken, Type [] genericTypeArguments, Type [] genericMethodArguments) {
356
357                         ResolveTokenError error;
358
359                         MemberInfo m = ResolveMemberToken (_impl, metadataToken, ptrs_from_types (genericTypeArguments), ptrs_from_types (genericMethodArguments), out error);
360                         if (m == null)
361                                 throw resolve_token_exception (metadataToken, error, "MemberInfo");
362                         else
363                                 return m;
364                 }
365
366                 public MethodBase ResolveMethod (int metadataToken) {
367                         return ResolveMethod (metadataToken, null, null);
368                 }
369
370                 public MethodBase ResolveMethod (int metadataToken, Type [] genericTypeArguments, Type [] genericMethodArguments) {
371                         ResolveTokenError error;
372
373                         IntPtr handle = ResolveMethodToken (_impl, metadataToken, ptrs_from_types (genericTypeArguments), ptrs_from_types (genericMethodArguments), out error);
374                         if (handle == IntPtr.Zero)
375                                 throw resolve_token_exception (metadataToken, error, "MethodBase");
376                         else
377                                 return MethodBase.GetMethodFromHandle (new RuntimeMethodHandle (handle));
378                 }
379
380                 public string ResolveString (int metadataToken) {
381                         ResolveTokenError error;
382
383                         string s = ResolveStringToken (_impl, metadataToken, out error);
384                         if (s == null)
385                                 throw resolve_token_exception (metadataToken, error, "string");
386                         else
387                                 return s;
388                 }
389
390                 public Type ResolveType (int metadataToken) {
391                         return ResolveType (metadataToken, null, null);
392                 }
393
394                 public Type ResolveType (int metadataToken, Type [] genericTypeArguments, Type [] genericMethodArguments) {
395                         ResolveTokenError error;
396
397                         IntPtr handle = ResolveTypeToken (_impl, metadataToken, ptrs_from_types (genericTypeArguments), ptrs_from_types (genericMethodArguments), out error);
398                         if (handle == IntPtr.Zero)
399                                 throw resolve_token_exception (metadataToken, error, "Type");
400                         else
401                                 return Type.GetTypeFromHandle (new RuntimeTypeHandle (handle));
402                 }
403
404                 public byte[] ResolveSignature (int metadataToken) {
405                         ResolveTokenError error;
406
407                     byte[] res = ResolveSignature (_impl, metadataToken, out error);
408                         if (res == null)
409                                 throw resolve_token_exception (metadataToken, error, "signature");
410                         else
411                                 return res;
412                 }
413 #endif
414
415                 internal static Type MonoDebugger_ResolveType (Module module, int token)
416                 {
417                         ResolveTokenError error;
418
419                         IntPtr handle = ResolveTypeToken (module._impl, token, null, null, out error);
420                         if (handle == IntPtr.Zero)
421                                 return null;
422                         else
423                                 return Type.GetTypeFromHandle (new RuntimeTypeHandle (handle));
424                 }
425
426                 // Mono Extension: returns the GUID of this module
427                 internal static Guid Mono_GetGuid (Module module)
428                 {
429                         return new Guid (module.GetGuidInternal ());
430                 }
431
432                 private static bool filter_by_type_name (Type m, object filterCriteria) {
433                         string s = (string)filterCriteria;
434                         if (s.EndsWith ("*"))
435                                 return m.Name.StartsWith (s.Substring (0, s.Length - 1));
436                         else
437                                 return m.Name == s;
438                 }
439
440                 private static bool filter_by_type_name_ignore_case (Type m, object filterCriteria) {
441                         string s = (string)filterCriteria;
442                         if (s.EndsWith ("*"))
443                                 return m.Name.ToLower ().StartsWith (s.Substring (0, s.Length - 1).ToLower ());
444                         else
445                                 return String.Compare (m.Name, s, true) == 0;
446                 }
447
448                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
449                 private extern string GetGuidInternal ();
450
451                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
452                 private extern Type GetGlobalType ();
453
454                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
455                 internal static extern IntPtr ResolveTypeToken (IntPtr module, int token, IntPtr[] type_args, IntPtr[] method_args, out ResolveTokenError error);
456
457                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
458                 internal static extern IntPtr ResolveMethodToken (IntPtr module, int token, IntPtr[] type_args, IntPtr[] method_args, out ResolveTokenError error);
459
460                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
461                 internal static extern IntPtr ResolveFieldToken (IntPtr module, int token, IntPtr[] type_args, IntPtr[] method_args, out ResolveTokenError error);
462
463                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
464                 internal static extern string ResolveStringToken (IntPtr module, int token, out ResolveTokenError error);
465
466                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
467                 internal static extern MemberInfo ResolveMemberToken (IntPtr module, int token, IntPtr[] type_args, IntPtr[] method_args, out ResolveTokenError error);
468
469                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
470                 internal static extern byte[] ResolveSignature (IntPtr module, int metadataToken, out ResolveTokenError error);
471
472                 [MethodImplAttribute (MethodImplOptions.InternalCall)]
473                 internal static extern void GetPEKind (IntPtr module, out PortableExecutableKinds peKind, out ImageFileMachine machine);
474
475 #if NET_1_1
476                 void _Module.GetIDsOfNames ([In] ref Guid riid, IntPtr rgszNames, uint cNames, uint lcid, IntPtr rgDispId)
477                 {
478                         throw new NotImplementedException ();
479                 }
480
481                 void _Module.GetTypeInfo (uint iTInfo, uint lcid, IntPtr ppTInfo)
482                 {
483                         throw new NotImplementedException ();
484                 }
485
486                 void _Module.GetTypeInfoCount (out uint pcTInfo)
487                 {
488                         throw new NotImplementedException ();
489                 }
490
491                 void _Module.Invoke (uint dispIdMember, [In] ref Guid riid, uint lcid, short wFlags, IntPtr pDispParams,
492                         IntPtr pVarResult, IntPtr pExcepInfo, IntPtr puArgErr)
493                 {
494                         throw new NotImplementedException ();
495                 }
496 #endif
497         }
498 }