Update mcs/class/System.Core/System/TimeZoneInfo.cs
[mono.git] / mcs / class / IKVM.Reflection / Emit / AssemblyBuilder.cs
index 633f09dfcc2b88a4d2939fc2dc0863422cef81b8..ceabeac73af79242e870daa2d81bc5e7b26b17a9 100644 (file)
@@ -1,5 +1,5 @@
 /*
-  Copyright (C) 2008-2011 Jeroen Frijters
+  Copyright (C) 2008-2012 Jeroen Frijters
 
   This software is provided 'as-is', without any express or implied
   warranty.  In no event will the authors be held liable for any damages
@@ -27,6 +27,7 @@ using System.Configuration.Assemblies;
 using System.IO;
 using System.Diagnostics;
 using System.Globalization;
+using System.Resources;
 using System.Security.Cryptography;
 using System.Security;
 using IKVM.Reflection.Metadata;
@@ -54,7 +55,9 @@ namespace IKVM.Reflection.Emit
                private PEFileKinds fileKind = PEFileKinds.Dll;
                private MethodInfo entryPoint;
                private VersionInfo versionInfo;
-               private ResourceSection unmanagedResources;
+               private byte[] win32icon;
+               private byte[] win32manifest;
+               private byte[] win32resources;
                private string imageRuntimeVersion;
                internal int mdStreamVersion = 0x20000;
                private Module pseudoManifestModule;
@@ -64,41 +67,13 @@ namespace IKVM.Reflection.Emit
                private readonly List<CustomAttributeBuilder> customAttributes = new List<CustomAttributeBuilder>();
                private readonly List<CustomAttributeBuilder> declarativeSecurity = new List<CustomAttributeBuilder>();
                private readonly List<Type> typeForwarders = new List<Type>();
-               private Dictionary<ScopedTypeName, Type> missingTypes;
 
                private struct ResourceFile
                {
                        internal string Name;
                        internal string FileName;
                        internal ResourceAttributes Attributes;
-               }
-
-               private struct ScopedTypeName : IEquatable<ScopedTypeName>
-               {
-                       private readonly Type declaringType;
-                       private readonly TypeName name;
-
-                       internal ScopedTypeName(Type declaringType, TypeName name)
-                       {
-                               this.declaringType = declaringType;
-                               this.name = name;
-                       }
-
-                       public override bool Equals(object obj)
-                       {
-                               ScopedTypeName? other = obj as ScopedTypeName?;
-                               return other != null && ((IEquatable<ScopedTypeName>)other.Value).Equals(this);
-                       }
-
-                       public override int GetHashCode()
-                       {
-                               return declaringType == null ? name.GetHashCode() : declaringType.GetHashCode() * 7 + name.GetHashCode();
-                       }
-
-                       bool IEquatable<ScopedTypeName>.Equals(ScopedTypeName other)
-                       {
-                               return other.declaringType == declaringType && other.name == name;
-                       }
+                       internal ResourceWriter Writer;
                }
 
                internal AssemblyBuilder(Universe universe, AssemblyName name, string dir, PermissionSet requiredPermissions, PermissionSet optionalPermissions, PermissionSet refusedPermissions)
@@ -106,11 +81,11 @@ namespace IKVM.Reflection.Emit
                {
                        this.name = name.Name;
                        SetVersionHelper(name.Version);
-                       if (name.CultureInfo != null && !string.IsNullOrEmpty(name.CultureInfo.Name))
+                       if (!string.IsNullOrEmpty(name.Culture))
                        {
-                               this.culture = name.CultureInfo.Name;
+                               this.culture = name.Culture;
                        }
-                       this.flags = name.Flags;
+                       this.flags = name.RawFlags;
                        this.hashAlgorithm = name.HashAlgorithm;
                        if (this.hashAlgorithm == AssemblyHashAlgorithm.None)
                        {
@@ -133,7 +108,7 @@ namespace IKVM.Reflection.Emit
                        this.requiredPermissions = requiredPermissions;
                        this.optionalPermissions = optionalPermissions;
                        this.refusedPermissions = refusedPermissions;
-                       if (universe.HasMscorlib && universe.Mscorlib.ImageRuntimeVersion != null)
+                       if (universe.HasMscorlib && !universe.Mscorlib.__IsMissing && universe.Mscorlib.ImageRuntimeVersion != null)
                        {
                                this.imageRuntimeVersion = universe.Mscorlib.ImageRuntimeVersion;
                        }
@@ -161,18 +136,24 @@ namespace IKVM.Reflection.Emit
                        }
                }
 
+               private void Rename(AssemblyName oldName)
+               {
+                       this.fullName = null;
+                       universe.RenameAssembly(this, oldName);
+               }
+
                public void __SetAssemblyVersion(Version version)
                {
                        AssemblyName oldName = GetName();
                        SetVersionHelper(version);
-                       universe.RenameAssembly(this, oldName);
+                       Rename(oldName);
                }
 
                public void __SetAssemblyCulture(string cultureName)
                {
                        AssemblyName oldName = GetName();
                        this.culture = cultureName;
-                       universe.RenameAssembly(this, oldName);
+                       Rename(oldName);
                }
 
                public void __SetAssemblyKeyPair(StrongNameKeyPair keyPair)
@@ -183,7 +164,7 @@ namespace IKVM.Reflection.Emit
                        {
                                this.publicKey = keyPair.PublicKey;
                        }
-                       universe.RenameAssembly(this, oldName);
+                       Rename(oldName);
                }
 
                // this is used in combination with delay signing
@@ -191,7 +172,7 @@ namespace IKVM.Reflection.Emit
                {
                        AssemblyName oldName = GetName();
                        this.publicKey = publicKey == null ? null : (byte[])publicKey.Clone();
-                       universe.RenameAssembly(this, oldName);
+                       Rename(oldName);
                }
 
                public void __SetAssemblyAlgorithmId(AssemblyHashAlgorithm hashAlgorithm)
@@ -201,7 +182,19 @@ namespace IKVM.Reflection.Emit
 
                public void __SetAssemblyFlags(AssemblyNameFlags flags)
                {
+                       AssemblyName oldName = GetName();
                        this.flags = flags;
+                       Rename(oldName);
+               }
+
+               public override AssemblyNameFlags __AssemblyFlags
+               {
+                       get { return flags; }
+               }
+
+               internal string Name
+               {
+                       get { return name; }
                }
 
                public override AssemblyName GetName()
@@ -209,19 +202,14 @@ namespace IKVM.Reflection.Emit
                        AssemblyName n = new AssemblyName();
                        n.Name = name;
                        n.Version = new Version(majorVersion, minorVersion, buildVersion, revisionVersion);
-                       n.Culture = culture;
+                       n.Culture = culture ?? "";
                        n.HashAlgorithm = hashAlgorithm;
-                       n.Flags = flags;
+                       n.RawFlags = flags;
                        n.SetPublicKey(publicKey != null ? (byte[])publicKey.Clone() : Empty<byte>.Array);
                        n.KeyPair = keyPair;
                        return n;
                }
 
-               public override string FullName
-               {
-                       get { return GetName().FullName; }
-               }
-
                public override string Location
                {
                        get { throw new NotSupportedException(); }
@@ -311,6 +299,7 @@ namespace IKVM.Reflection.Emit
 
                        foreach (ModuleBuilder moduleBuilder in modules)
                        {
+                               moduleBuilder.SetIsSaved();
                                moduleBuilder.PopulatePropertyAndEventTables();
 
                                if (manifestModule == null
@@ -366,6 +355,10 @@ namespace IKVM.Reflection.Emit
                                manifestModule.AddDeclarativeSecurity(token, requestRefuse, refusedPermissions);
                        }
 
+                       ResourceSection unmanagedResources = versionInfo != null || win32icon != null || win32manifest != null || win32resources != null
+                               ? new ResourceSection()
+                               : null;
+
                        if (versionInfo != null)
                        {
                                versionInfo.SetName(GetName());
@@ -380,13 +373,24 @@ namespace IKVM.Reflection.Emit
                                }
                                ByteBuffer versionInfoData = new ByteBuffer(512);
                                versionInfo.Write(versionInfoData);
-                               if (unmanagedResources == null)
-                               {
-                                       unmanagedResources = new ResourceSection();
-                               }
                                unmanagedResources.AddVersionInfo(versionInfoData);
                        }
 
+                       if (win32icon != null)
+                       {
+                               unmanagedResources.AddIcon(win32icon);
+                       }
+
+                       if (win32manifest != null)
+                       {
+                               unmanagedResources.AddManifest(win32manifest, fileKind == PEFileKinds.Dll ? (ushort)2 : (ushort)1);
+                       }
+
+                       if (win32resources != null)
+                       {
+                               unmanagedResources.ExtractResources(win32resources);
+                       }
+
                        foreach (CustomAttributeBuilder cab in customAttributes)
                        {
                                // we intentionally don't filter out the version info (pseudo) custom attributes (to be compatible with .NET)
@@ -402,6 +406,11 @@ namespace IKVM.Reflection.Emit
 
                        foreach (ResourceFile resfile in resourceFiles)
                        {
+                               if (resfile.Writer != null)
+                               {
+                                       resfile.Writer.Generate();
+                                       resfile.Writer.Close();
+                               }
                                int fileToken = AddFile(manifestModule, resfile.FileName, 1 /*ContainsNoMetaData*/);
                                ManifestResourceTable.Record rec = new ManifestResourceTable.Record();
                                rec.Offset = 0;
@@ -416,6 +425,7 @@ namespace IKVM.Reflection.Emit
                        foreach (ModuleBuilder moduleBuilder in modules)
                        {
                                moduleBuilder.FillAssemblyRefTable();
+                               moduleBuilder.EmitResources();
                                if (moduleBuilder != manifestModule)
                                {
                                        int fileToken;
@@ -464,11 +474,7 @@ namespace IKVM.Reflection.Emit
                                        ModuleWriter.HashChunk(fs, cs, buf, (int)fs.Length);
                                }
                        }
-                       FileTable.Record file = new FileTable.Record();
-                       file.Flags = flags;
-                       file.Name = manifestModule.Strings.Add(Path.GetFileName(fileName));
-                       file.HashValue = manifestModule.Blobs.Add(ByteBuffer.Wrap(hash.Hash));
-                       return 0x26000000 + manifestModule.File.AddRecord(file);
+                       return manifestModule.__AddModule(flags, Path.GetFileName(fileName), hash.Hash);
                }
 
                public void AddResourceFile(string name, string fileName)
@@ -485,13 +491,45 @@ namespace IKVM.Reflection.Emit
                        resourceFiles.Add(resfile);
                }
 
+               public IResourceWriter DefineResource(string name, string description, string fileName)
+               {
+                       return DefineResource(name, description, fileName, ResourceAttributes.Public);
+               }
+
+               public IResourceWriter DefineResource(string name, string description, string fileName, ResourceAttributes attribute)
+               {
+                       // FXBUG we ignore the description, because there is no such thing
+
+                       string fullPath = fileName;
+                       if (dir != null)
+                       {
+                               fullPath = Path.Combine(dir, fileName);
+                       }
+                       ResourceWriter rw = new ResourceWriter(fullPath);
+                       ResourceFile resfile;
+                       resfile.Name = name;
+                       resfile.FileName = fileName;
+                       resfile.Attributes = attribute;
+                       resfile.Writer = rw;
+                       resourceFiles.Add(resfile);
+                       return rw;
+               }
+
                public void DefineVersionInfoResource()
                {
+                       if (versionInfo != null || win32resources != null)
+                       {
+                               throw new ArgumentException("Native resource has already been defined.");
+                       }
                        versionInfo = new VersionInfo();
                }
 
                public void DefineVersionInfoResource(string product, string productVersion, string company, string copyright, string trademark)
                {
+                       if (versionInfo != null || win32resources != null)
+                       {
+                               throw new ArgumentException("Native resource has already been defined.");
+                       }
                        versionInfo = new VersionInfo();
                        versionInfo.product = product;
                        versionInfo.informationalVersion = productVersion;
@@ -502,17 +540,32 @@ namespace IKVM.Reflection.Emit
 
                public void __DefineIconResource(byte[] iconFile)
                {
-                       unmanagedResources = new ResourceSection();
-                       unmanagedResources.AddIcon(iconFile);
+                       if (win32icon != null || win32resources != null)
+                       {
+                               throw new ArgumentException("Native resource has already been defined.");
+                       }
+                       win32icon = (byte[])iconFile.Clone();
+               }
+
+               public void __DefineManifestResource(byte[] manifest)
+               {
+                       if (win32manifest != null || win32resources != null)
+                       {
+                               throw new ArgumentException("Native resource has already been defined.");
+                       }
+                       win32manifest = (byte[])manifest.Clone();
                }
 
                public void __DefineUnmanagedResource(byte[] resource)
                {
+                       if (versionInfo != null || win32icon != null || win32manifest != null || win32resources != null)
+                       {
+                               throw new ArgumentException("Native resource has already been defined.");
+                       }
                        // The standard .NET DefineUnmanagedResource(byte[]) is useless, because it embeds "resource" (as-is) as the .rsrc section,
                        // but it doesn't set the PE file Resource Directory entry to point to it. That's why we have a renamed version, which behaves
                        // like DefineUnmanagedResource(string).
-                       unmanagedResources = new ResourceSection();
-                       unmanagedResources.ExtractResources(resource);
+                       win32resources = (byte[])resource.Clone();
                }
 
                public void DefineUnmanagedResource(string resourceFileName)
@@ -557,33 +610,25 @@ namespace IKVM.Reflection.Emit
                        return null;
                }
 
-               internal override Type GetMissingType(TypeName name)
+               internal override Type FindTypeIgnoreCase(TypeName lowerCaseName)
                {
-                       return GetMissingType(this.ManifestModule, null, name);
-               }
-
-               internal Type GetMissingType(Module module, Type declaringType, TypeName name)
-               {
-                       if (missingTypes == null)
-                       {
-                               return null;
-                       }
-                       ScopedTypeName stn = new ScopedTypeName(declaringType, name);
-                       Type type;
-                       if (!missingTypes.TryGetValue(stn, out type))
+                       foreach (ModuleBuilder mb in modules)
                        {
-                               type = new MissingType(module, declaringType, name.Namespace, name.Name);
-                               missingTypes.Add(stn, type);
+                               Type type = mb.FindTypeIgnoreCase(lowerCaseName);
+                               if (type != null)
+                               {
+                                       return type;
+                               }
                        }
-                       return type;
-               }
-
-               public void __EnableMissingTypeResolution()
-               {
-                       if (missingTypes == null)
+                       foreach (Module module in addedModules)
                        {
-                               missingTypes = new Dictionary<ScopedTypeName, Type>();
+                               Type type = module.FindTypeIgnoreCase(lowerCaseName);
+                               if (type != null)
+                               {
+                                       return type;
+                               }
                        }
+                       return null;
                }
 
                public override string ImageRuntimeVersion
@@ -697,9 +742,14 @@ namespace IKVM.Reflection.Emit
                        }
                        return list;
                }
+
+               internal bool IsWindowsRuntime
+               {
+                       get { return (flags & (AssemblyNameFlags)0x200) != 0; }
+               }
        }
 
-       sealed class ManifestModule : Module
+       sealed class ManifestModule : NonPEModule
        {
                private readonly AssemblyBuilder assembly;
                private readonly Guid guid = Guid.NewGuid();
@@ -725,6 +775,11 @@ namespace IKVM.Reflection.Emit
                        return null;
                }
 
+               internal override Type FindTypeIgnoreCase(TypeName lowerCaseName)
+               {
+                       return null;
+               }
+
                internal override void  GetTypesImpl(List<Type> list)
                {
                }
@@ -744,54 +799,14 @@ namespace IKVM.Reflection.Emit
                        get { return guid; }
                }
 
-               public override Type ResolveType(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
-               {
-                       throw new ArgumentException();
-               }
-
-               public override MethodBase ResolveMethod(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
-               {
-                       throw new ArgumentException();
-               }
-
-               public override FieldInfo ResolveField(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
-               {
-                       throw new ArgumentException();
-               }
-
-               public override MemberInfo ResolveMember(int metadataToken, Type[] genericTypeArguments, Type[] genericMethodArguments)
-               {
-                       throw new ArgumentException();
-               }
-
-               public override string ResolveString(int metadataToken)
-               {
-                       throw new ArgumentException();
-               }
-
-               public override Type[] __ResolveOptionalParameterTypes(int metadataToken)
-               {
-                       throw new ArgumentException();
-               }
-
                public override string ScopeName
                {
                        get { return "RefEmit_InMemoryManifestModule"; }
                }
 
-               public override AssemblyName[] __GetReferencedAssemblies()
-               {
-                       throw new InvalidOperationException();
-               }
-
-               internal override Type GetModuleType()
-               {
-                       throw new InvalidOperationException();
-               }
-
-               internal override IKVM.Reflection.Reader.ByteReader GetBlob(int blobIndex)
+               protected override Exception NotSupportedException()
                {
-                       throw new InvalidOperationException();
+                       return new InvalidOperationException();
                }
        }
 }