New test.
[mono.git] / mcs / class / corlib / System.Reflection / Assembly.cs
index 664ce1166d9f4abda4bc7020665f7dfecb23b99b..2442e925b960ebc00658853278a1db1651c7b668 100644 (file)
@@ -31,33 +31,41 @@ using System.Security;
 using System.Security.Policy;
 using System.Security.Permissions;
 using System.Runtime.Serialization;
+using System.Reflection;
 using System.Reflection.Emit;
 using System.IO;
 using System.Globalization;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 using System.Collections;
+using System.Collections.Generic;
 using System.Configuration.Assemblies;
 
 using Mono.Security;
 
 namespace System.Reflection {
 
-#if NET_2_0
+#pragma warning disable 659 // overrides Equals but not GetHashCode
+
        [ComVisible (true)]
        [ComDefaultInterfaceAttribute (typeof (_Assembly))]
-#endif
        [Serializable]
        [ClassInterface(ClassInterfaceType.None)]
-       public class Assembly : System.Reflection.ICustomAttributeProvider, _Assembly,
-               System.Security.IEvidenceFactory, System.Runtime.Serialization.ISerializable {
-
+#if NET_2_1
+       public partial class Assembly : ICustomAttributeProvider, _Assembly {
+#elif NET_4_0
+       public abstract class Assembly : ICustomAttributeProvider, _Assembly, IEvidenceFactory, ISerializable {
+#else
+       public partial class Assembly : ICustomAttributeProvider, _Assembly, IEvidenceFactory, ISerializable {
+#endif
                internal class ResolveEventHolder {
                        public event ModuleResolveEventHandler ModuleResolve;
                }
 
                // Note: changes to fields must be reflected in _MonoReflectionAssembly struct (object-internals.h)
+#pragma warning disable 649
                private IntPtr _mono_assembly;
+#pragma warning restore 649
 
                private ResolveEventHolder resolve_event_holder;
                private Evidence _evidence;
@@ -69,7 +77,12 @@ namespace System.Reflection {
                private bool fromByteArray;
                private string assemblyName;
 
-               internal Assembly () 
+#if NET_4_0
+               protected
+#else
+               internal
+#endif
+               Assembly () 
                {
                        resolve_event_holder = new ResolveEventHolder ();
                }
@@ -93,18 +106,19 @@ namespace System.Reflection {
                private extern string get_code_base (bool escaped);
 
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               private extern string get_location ();
+               private extern string get_fullname ();
 
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               private extern string InternalImageRuntimeVersion ();
+               private extern string get_location ();
 
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               private extern bool get_global_assembly_cache ();
+               private extern string InternalImageRuntimeVersion ();
 
                // SECURITY: this should be the only caller to icall get_code_base
                private string GetCodeBase (bool escaped)
                {
                        string cb = get_code_base (escaped);
+#if !NET_2_1
                        if (SecurityManager.SecurityEnabled) {
                                // we cannot divulge local file informations
                                if (String.Compare ("FILE://", 0, cb, 0, 7, true, CultureInfo.InvariantCulture) == 0) {
@@ -112,6 +126,7 @@ namespace System.Reflection {
                                        new FileIOPermission (FileIOPermissionAccess.PathDiscovery, file).Demand ();
                                }
                        }
+#endif
                        return cb;
                }
 
@@ -137,7 +152,7 @@ namespace System.Reflection {
                        [MethodImplAttribute (MethodImplOptions.InternalCall)]
                        get;
                }
-
+#if !MOONLIGHT
                public virtual Evidence Evidence {
                        [SecurityPermission (SecurityAction.Demand, ControlEvidence = true)]
                        get { return UnprotectedGetEvidence (); }
@@ -156,14 +171,12 @@ namespace System.Reflection {
                        return _evidence;
                }
 
-               public bool GlobalAssemblyCache {
-                       get {
-                               return get_global_assembly_cache ();
-                       }
-               }
+               [MethodImplAttribute (MethodImplOptions.InternalCall)]
+               internal extern bool get_global_assembly_cache ();
 
+#endif
                internal bool FromByteArray {
-                       set { fromByteArray = true; }
+                       set { fromByteArray = value; }
                }
 
                public virtual String Location {
@@ -172,22 +185,22 @@ namespace System.Reflection {
                                        return String.Empty;
 
                                string loc = get_location ();
+#if !NET_2_1
                                if ((loc != String.Empty) && SecurityManager.SecurityEnabled) {
                                        // we cannot divulge local file informations
                                        new FileIOPermission (FileIOPermissionAccess.PathDiscovery, loc).Demand ();
                                }
+#endif
                                return loc;
                        }
                }
 
-#if NET_1_1
                [ComVisible (false)]
                public virtual string ImageRuntimeVersion {
                        get {
                                return InternalImageRuntimeVersion ();
                        }
                }
-#endif
 
                [SecurityPermission (SecurityAction.LinkDemand, SerializationFormatter = true)]
                public virtual void GetObjectData (SerializationInfo info, StreamingContext context)
@@ -198,13 +211,6 @@ namespace System.Reflection {
                        UnitySerializationHolder.GetAssemblyData (this, info, context);
                }
 
-#if ONLY_1_1
-               public new Type GetType ()
-               {
-                       return base.GetType ();
-               }
-#endif
-
                public virtual bool IsDefined (Type attributeType, bool inherit)
                {
                        return MonoCustomAttrs.IsDefined (this, attributeType, inherit);
@@ -234,18 +240,28 @@ namespace System.Reflection {
                        if (names == null)
                                return new FileStream [0];
 
-                       FileStream[] res = new FileStream [names.Length];
-                       for (int i = 0; i < names.Length; ++i)
-                               res [i] = new FileStream (names [i], FileMode.Open, FileAccess.Read);
+                       string location = Location;
+
+                       FileStream[] res;
+                       if (location != String.Empty) {
+                               res = new FileStream [names.Length + 1];
+                               res [0] = new FileStream (location, FileMode.Open, FileAccess.Read);
+                               for (int i = 0; i < names.Length; ++i)
+                                       res [i + 1] = new FileStream (names [i], FileMode.Open, FileAccess.Read);
+                       } else {
+                               res = new FileStream [names.Length];
+                               for (int i = 0; i < names.Length; ++i)
+                                       res [i] = new FileStream (names [i], FileMode.Open, FileAccess.Read);
+                       }
                        return res;
                }
 
                public virtual FileStream GetFile (String name)
                {
                        if (name == null)
-                               throw new ArgumentNullException ("name");
+                               throw new ArgumentNullException (null, "Name cannot be null.");
                        if (name.Length == 0)
-                               throw new ArgumentException ("name");
+                               throw new ArgumentException ("Empty name is not valid");
 
                        string filename = (string)GetFilesInternal (name, true);
                        if (filename != null)
@@ -273,14 +289,16 @@ namespace System.Reflection {
                                return info.ReferencedAssembly.GetManifestResourceStream (name);
                        if ((info.FileName != null) && (info.ResourceLocation == 0)) {
                                if (fromByteArray)
-#if NET_2_0
                                        throw new FileNotFoundException (info.FileName);
-#else
-                                       return null;
-#endif
 
-                               string filename = Path.Combine (Path.GetDirectoryName (Location),
-                                                                                       info.FileName);
+                               string location = Path.GetDirectoryName (Location);
+                               string filename = Path.Combine (location, info.FileName);
+#if MOONLIGHT
+                               // we don't control the content of 'info.FileName' so we want to make sure we keep to ourselves
+                               filename = Path.GetFullPath (filename);
+                               if (!filename.StartsWith (location))
+                                       throw new SecurityException ("non-rooted access to manifest resource");
+#endif
                                return new FileStream (filename, FileMode.Open, FileAccess.Read);
                        }
 
@@ -290,7 +308,10 @@ namespace System.Reflection {
                        if (data == (IntPtr) 0)
                                return null;
                        else {
-                               IntPtrStream stream = new IntPtrStream (data, size);
+                               UnmanagedMemoryStream stream;
+                               unsafe {
+                                       stream = new UnmanagedMemoryStream ((byte*) data, size);
+                               }
                                /* 
                                 * The returned pointer points inside metadata, so
                                 * we have to increase the refcount of the module, and decrease
@@ -319,7 +340,7 @@ namespace System.Reflection {
                }
 
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               private extern Type[] GetTypes (bool exportedOnly);
+               internal virtual extern Type[] GetTypes (bool exportedOnly);
                
                public virtual Type[] GetTypes ()
                {
@@ -343,17 +364,9 @@ namespace System.Reflection {
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
                internal extern Type InternalGetType (Module module, String name, Boolean throwOnError, Boolean ignoreCase);
 
-               public Type GetType (string name, bool throwOnError, bool ignoreCase)
-               {
-                       if (name == null)
-                               throw new ArgumentNullException (name);
-
-                       return InternalGetType (null, name, throwOnError, ignoreCase);
-               }
-
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
                internal extern static void InternalGetAssemblyName (string assemblyFile, AssemblyName aname);
-               
+
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
                static extern void FillName (Assembly ass, AssemblyName aname);
 
@@ -387,10 +400,7 @@ namespace System.Reflection {
                        if (assemblyName != null)
                                return assemblyName;
 
-                       AssemblyName aname = new AssemblyName ();
-                       FillName (this, aname);
-                       assemblyName = aname.ToString ();
-
+                       assemblyName = get_fullname ();
                        return assemblyName;
                }
 
@@ -410,12 +420,12 @@ namespace System.Reflection {
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
                public static extern Assembly GetEntryAssembly();
 
-               public Assembly GetSatelliteAssembly (CultureInfo culture)
+               internal Assembly GetSatelliteAssemblyNoThrow (CultureInfo culture, Version version)
                {
-                       return GetSatelliteAssembly (culture, null);
+                       return GetSatelliteAssembly (culture, version, false);
                }
 
-               public Assembly GetSatelliteAssembly (CultureInfo culture, Version version)
+               internal Assembly GetSatelliteAssembly (CultureInfo culture, Version version, bool throwOnError)
                {
                        if (culture == null)
                                throw new ArgumentException ("culture");
@@ -426,7 +436,33 @@ namespace System.Reflection {
 
                        aname.CultureInfo = culture;
                        aname.Name = aname.Name + ".resources";
-                       return Load (aname);
+                       Assembly assembly;
+
+                       try {
+                               assembly = AppDomain.CurrentDomain.LoadSatellite (aname, false);
+                               if (assembly != null)
+                                       return assembly;
+                       } catch (FileNotFoundException) {
+                               assembly = null;
+                               // ignore
+                       }
+
+                       // Try the assembly directory
+                       string location = Path.GetDirectoryName (Location);
+                       string fullName = Path.Combine (location, Path.Combine (culture.Name, aname.Name + ".dll"));
+#if MOONLIGHT
+                       // it's unlikely that culture.Name or aname.Name could contain stuff like ".." but...
+                       fullName = Path.GetFullPath (fullName);
+                       if (!fullName.StartsWith (location)) {
+                               if (throwOnError)
+                                       throw new SecurityException ("non-rooted access to satellite assembly");
+                               return null;
+                       }
+#endif
+                       if (!throwOnError && !File.Exists (fullName))
+                               return null;
+
+                       return LoadFrom (fullName);
                }
                
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
@@ -437,18 +473,24 @@ namespace System.Reflection {
                        return LoadFrom (assemblyFile, false);
                }
 
+#if NET_4_0
+               [Obsolete]
+#endif
                public static Assembly LoadFrom (String assemblyFile, Evidence securityEvidence)
                {
                        Assembly a = LoadFrom (assemblyFile, false);
+#if !NET_2_1
                        if ((a != null) && (securityEvidence != null)) {
                                // merge evidence (i.e. replace defaults with provided evidences)
                                a.Evidence.Merge (securityEvidence);
                        }
+#endif
                        return a;
                }
 
-#if NET_1_1
-
+#if NET_4_0
+               [Obsolete]
+#endif
                [MonoTODO("This overload is not currently implemented")]
                // FIXME: What are we missing?
                public static Assembly LoadFrom (String assemblyFile, Evidence securityEvidence, byte[] hashValue, AssemblyHashAlgorithm hashAlgorithm)
@@ -460,6 +502,9 @@ namespace System.Reflection {
                        throw new NotImplementedException ();
                }
 
+#if NET_4_0
+               [Obsolete]
+#endif
                public static Assembly LoadFile (String path, Evidence securityEvidence)
                {
                        if (path == null)
@@ -474,13 +519,15 @@ namespace System.Reflection {
                {
                        return LoadFile (path, null);
                }
-#endif
 
                public static Assembly Load (String assemblyString)
                {
                        return AppDomain.CurrentDomain.Load (assemblyString);
                }
-               
+
+#if NET_4_0
+               [Obsolete]
+#endif         
                public static Assembly Load (String assemblyString, Evidence assemblySecurity)
                {
                        return AppDomain.CurrentDomain.Load (assemblyString, assemblySecurity);
@@ -491,6 +538,9 @@ namespace System.Reflection {
                        return AppDomain.CurrentDomain.Load (assemblyRef);
                }
 
+#if NET_4_0
+               [Obsolete]
+#endif
                public static Assembly Load (AssemblyName assemblyRef, Evidence assemblySecurity)
                {
                        return AppDomain.CurrentDomain.Load (assemblyRef, assemblySecurity);
@@ -506,21 +556,23 @@ namespace System.Reflection {
                        return AppDomain.CurrentDomain.Load (rawAssembly, rawSymbolStore);
                }
 
+#if NET_4_0
+               [Obsolete]
+#endif
                public static Assembly Load (Byte[] rawAssembly, Byte[] rawSymbolStore,
                                             Evidence securityEvidence)
                {
                        return AppDomain.CurrentDomain.Load (rawAssembly, rawSymbolStore, securityEvidence);
                }
 
-#if NET_2_0
                public static Assembly ReflectionOnlyLoad (byte[] rawAssembly)
                {
                        return AppDomain.CurrentDomain.Load (rawAssembly, null, null, true);
                }
 
-               public static Assembly ReflectionOnlyLoad (string assemblyName
+               public static Assembly ReflectionOnlyLoad (string assemblyString
                {
-                       return AppDomain.CurrentDomain.Load (assemblyName, null, true);
+                       return AppDomain.CurrentDomain.Load (assemblyString, null, true);
                }
 
                public static Assembly ReflectionOnlyLoadFrom (string assemblyFile) 
@@ -530,10 +582,9 @@ namespace System.Reflection {
                        
                        return LoadFrom (assemblyFile, true);
                }
-#endif
 
-#if NET_2_0
-               [Obsolete ("")]
+#if NET_4_0
+               [Obsolete]
 #endif
                public static Assembly LoadWithPartialName (string partialName)
                {
@@ -547,7 +598,11 @@ namespace System.Reflection {
                }
 
                [MonoTODO ("Not implemented")]
-               public Module LoadModule (string moduleName, byte [] rawModule, byte [] rawSymbolStore)
+               public
+#if NET_4_0
+               virtual
+#endif
+               Module LoadModule (string moduleName, byte [] rawModule, byte [] rawSymbolStore)
                {
                        throw new NotImplementedException ();
                }
@@ -555,8 +610,8 @@ namespace System.Reflection {
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
                private static extern Assembly load_with_partial_name (string name, Evidence e);
 
-#if NET_2_0
-               [Obsolete ("")]
+#if NET_4_0
+               [Obsolete]
 #endif
                public static Assembly LoadWithPartialName (string partialName, Evidence securityEvidence)
                {
@@ -600,7 +655,11 @@ namespace System.Reflection {
                        }
                }
 
-               public Object CreateInstance (String typeName, Boolean ignoreCase,
+               public
+#if NET_4_0
+               virtual
+#endif
+               Object CreateInstance (String typeName, Boolean ignoreCase,
                                              BindingFlags bindingAttr, Binder binder,
                                              Object[] args, CultureInfo culture,
                                              Object[] activationAttributes)
@@ -621,49 +680,14 @@ namespace System.Reflection {
                        return GetLoadedModules (false);
                }
 
-               // FIXME: Currently, the two sets of modules are equal
-               public Module[] GetLoadedModules (bool getResourceModules)
-               {
-                       return GetModules (getResourceModules);
-               }
-
                public Module[] GetModules ()
                {
                        return GetModules (false);
                }
 
-               public Module GetModule (String name)
-               {
-                       if (name == null)
-                               throw new ArgumentNullException ("name");
-                       if (name.Length == 0)
-                               throw new ArgumentException ("Name can't be empty");
-
-                       Module[] modules = GetModules (true);
-                       foreach (Module module in modules) {
-                               if (module.ScopeName == name)
-                                       return module;
-                       }
-
-                       return null;
-               }
-
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               internal extern Module[] GetModulesInternal ();
+               internal virtual extern Module[] GetModulesInternal ();
 
-               public Module[] GetModules (bool getResourceModules) {
-                       Module[] modules = GetModulesInternal ();
-
-                       if (!getResourceModules) {
-                               ArrayList result = new ArrayList (modules.Length);
-                               foreach (Module m in modules)
-                                       if (!m.IsResource ())
-                                               result.Add (m);
-                               return (Module[])result.ToArray (typeof (Module));
-                       }
-                       else
-                               return modules;
-               }
 
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
                internal extern string[] GetNamespaces ();
@@ -678,7 +702,7 @@ namespace System.Reflection {
                public extern static Assembly GetCallingAssembly ();
 
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
-               public extern AssemblyName[] GetReferencedAssemblies ();
+               internal static extern AssemblyName[] GetReferencedAssemblies (Assembly module);
 
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
                private extern bool GetManifestResourceInfoInternal (String name, ManifestResourceInfo info);
@@ -698,8 +722,9 @@ namespace System.Reflection {
                }
 
                private class ResourceCloseHandler {
-
+#pragma warning disable 169, 414
                        Module module;
+#pragma warning restore 169, 414                       
 
                        public ResourceCloseHandler (Module module) {
                                this.module = module;
@@ -718,19 +743,16 @@ namespace System.Reflection {
                [MethodImplAttribute (MethodImplOptions.InternalCall)]
                internal static extern int MonoDebugger_GetMethodToken (MethodBase method);
 
-#if NET_2_0
-               [MonoTODO ("Always returns zero")]
+               [MonoTODO ("Currently it always returns zero")]
                [ComVisible (false)]
-               public long HostContext {
+               public
+#if NET_4_0
+               virtual
+#endif
+               long HostContext {
                        get { return 0; }
                }
 
-               [ComVisible (false)]
-               public Module ManifestModule {
-                       get {
-                               return GetManifestModule ();
-                       }
-               }
 
                internal virtual Module GetManifestModule () {
                        return GetManifestModuleInternal ();
@@ -744,8 +766,26 @@ namespace System.Reflection {
                        [MethodImplAttribute (MethodImplOptions.InternalCall)]
                        get;
                }
+
+               public override bool Equals (object o)
+               {
+                       if (((object) this) == o)
+                               return true;
+
+                       if (o == null)
+                               return false;
+                       
+                       Assembly other = (Assembly) o;
+                       return other._mono_assembly == _mono_assembly;
+               }
+               
+#if NET_4_0
+               public virtual IList<CustomAttributeData> GetCustomAttributesData () {
+                       return CustomAttributeData.GetCustomAttributes (this);
+               }
 #endif
 
+#if !MOONLIGHT
                // Code Access Security
 
                internal void Resolve () 
@@ -826,5 +866,58 @@ namespace System.Reflection {
                                }
                        }
                }
+#endif
+
+#if NET_4_0
+               static Exception CreateNIE ()
+               {
+                       return new NotSupportedException ("Derived classes must implement it");
+               }
+
+               public virtual Type GetType (string name, bool throwOnError, bool ignoreCase)
+               {
+                       throw CreateNIE ();
+               }
+
+               public virtual Module GetModule (String name)
+               {
+                       throw CreateNIE ();
+               }
+
+               public virtual AssemblyName[] GetReferencedAssemblies ()
+               {
+                       throw CreateNIE ();
+               }
+
+               public virtual Module[] GetModules (bool getResourceModules)
+               {
+                       throw CreateNIE ();
+               }
+
+               public virtual Module[] GetLoadedModules (bool getResourceModules)
+               {
+                       throw CreateNIE ();
+               }
+
+               public virtual Assembly GetSatelliteAssembly (CultureInfo culture)
+               {
+                       throw CreateNIE ();
+               }
+
+               public virtual Assembly GetSatelliteAssembly (CultureInfo culture, Version version)
+               {
+                       throw CreateNIE ();
+               }
+
+               public virtual Module ManifestModule {
+                       get { throw CreateNIE (); }
+               }
+
+               public virtual bool GlobalAssemblyCache {
+                       get { throw CreateNIE (); }
+               }
+#endif
        }
 }
+
+#pragma warning restore 659