2010-06-05 Marek Habersack <mhabersack@novell.com>
[mono.git] / mcs / class / System.Web / System.Web.Compilation / AspComponentFoundry.cs
index 8169a4f692f98bd5e9dadacf8143d27a510a7ec7..cc3268e383301e078c72bfc23d178c0f2da628c1 100644 (file)
 //
 using System;
 using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
 using System.IO;
 using System.Reflection;
-
-#if NET_2_0
-using System.Collections.Generic;
 using System.Web;
 using System.Web.Configuration;
 using System.Web.UI;
-#endif
+using System.Web.Util;
 
 namespace System.Web.Compilation
 {
-       internal class AspComponentFoundry
+       class AspComponentFoundry
        {
-               private Hashtable foundries;
-
+               Hashtable foundries;
+               Dictionary <string, AspComponent> components;
+               Dictionary <string, AspComponent> Components {
+                       get {
+                               if (components == null)
+                                       components = new Dictionary <string, AspComponent> (StringComparer.OrdinalIgnoreCase);
+                               return components;
+                       }
+               }
+               
                public AspComponentFoundry ()
                {
-#if NET_2_0
                        foundries = new Hashtable (StringComparer.InvariantCultureIgnoreCase);
-#else
-                       foundries = new Hashtable (CaseInsensitiveHashCodeProvider.DefaultInvariant,
-                                                  CaseInsensitiveComparer.DefaultInvariant);
-#endif
-
                        Assembly sw = typeof (AspComponentFoundry).Assembly;
                        RegisterFoundry ("asp", sw, "System.Web.UI.WebControls");
                        RegisterFoundry ("", "object", typeof (System.Web.UI.ObjectTag));
-
-#if NET_2_0
                        RegisterConfigControls ();
-#endif
                }
 
-               public Type GetComponentType (string foundryName, string tag)
-               {                       
-                       object o = foundries [foundryName];
-                       if (o == null)
+               public AspComponent GetComponent (string tagName)
+               {
+                       if (tagName == null || tagName.Length == 0)
                                return null;
+                       
+                       if (components != null) {
+                               AspComponent ret;
+                               if (components.TryGetValue (tagName, out ret))
+                                       return ret;
+                       }
 
-                       if (o is Foundry)
-                               return ((Foundry)o).GetType (tag);
+                       string foundryName, tag;
+                       int colon = tagName.IndexOf (':');
+                       if (colon > -1) {
+                               if (colon == 0)
+                                       throw new Exception ("Empty TagPrefix is not valid.");
+                               if (colon + 1 == tagName.Length)
+                                       return null;
+                               foundryName = tagName.Substring (0, colon);
+                               tag = tagName.Substring (colon + 1);
+                       } else {
+                               foundryName = String.Empty;
+                               tag = tagName;
+                       }
+                       
+                       object o = foundries [foundryName];                     
+                       if (o == null)
+                               return null;
 
+                       Foundry foundry = o as Foundry;
+                       if (foundry != null)
+                               return CreateComponent (foundry, tagName, foundryName, tag);
+                       
                        ArrayList af = o as ArrayList;
                        if (af == null)
                                return null;
 
-                       Type t;
+                       AspComponent component = null;
                        Exception e = null;
                        foreach (Foundry f in af) {
                                try {
-                                       t = f.GetType (tag);
-                                       if (t != null)
-                                               return t;
+                                       component = CreateComponent (f, tagName, foundryName, tag);
+                                       if (component != null)
+                                               return component;
                                } catch (Exception ex) {
                                        e = ex;
                                }
@@ -94,37 +116,74 @@ namespace System.Web.Compilation
                        return null;
                }
 
+               AspComponent CreateComponent (Foundry foundry, string tagName, string prefix, string tag)
+               {
+                       string source, ns;
+                       Type type;
+
+                       type = foundry.GetType (tag, out source, out ns);
+                       if (type == null)
+                               return null;
+                       
+                       AspComponent ret = new AspComponent (type, ns, prefix, source, foundry.FromConfig);
+                       Dictionary <string, AspComponent> components = Components;
+                       components.Add (tagName, ret);
+                       return ret;
+               }
+               
+               public void RegisterFoundry (string foundryName, Assembly assembly, string nameSpace)
+               {
+                       RegisterFoundry (foundryName, assembly, nameSpace, false);
+               }
+               
                public void RegisterFoundry (string foundryName,
                                             Assembly assembly,
-                                            string nameSpace)
+                                            string nameSpace,
+                                            bool fromConfig)
                {
                        AssemblyFoundry foundry = new AssemblyFoundry (assembly, nameSpace);
-                       InternalRegister (foundryName, foundry);
+                       foundry.FromConfig = fromConfig;
+                       InternalRegister (foundryName, foundry, fromConfig);
                }
 
+               public void RegisterFoundry (string foundryName, string tagName, Type type)
+               {
+                       RegisterFoundry (foundryName, tagName, type, false);
+               }
+               
                public void RegisterFoundry (string foundryName,
                                             string tagName,
-                                            Type type)
+                                            Type type,
+                                            bool fromConfig)
                {
                        TagNameFoundry foundry = new TagNameFoundry (tagName, type);
-                       InternalRegister (foundryName, foundry);
+                       foundry.FromConfig = fromConfig;
+                       InternalRegister (foundryName, foundry, fromConfig);
                }
 
-#if NET_2_0
+               public void RegisterFoundry (string foundryName, string tagName, string source)
+               {
+                       RegisterFoundry (foundryName, tagName, source, false);
+               }
+               
                public void RegisterFoundry (string foundryName,
                                             string tagName,
-                                            string source)
+                                            string source,
+                                            bool fromConfig)
                {
                        TagNameFoundry foundry = new TagNameFoundry (tagName, source);
-                       InternalRegister (foundryName, foundry);
+                       foundry.FromConfig = fromConfig;
+                       InternalRegister (foundryName, foundry, fromConfig);
                }
 
                public void RegisterAssemblyFoundry (string foundryName,
                                                     string assemblyName,
-                                                    string nameSpace)
+                                                    string nameSpace,
+                                                    bool fromConfig)
                {
                        AssemblyFoundry foundry = new AssemblyFoundry (assemblyName, nameSpace);
-                       InternalRegister (foundryName, foundry);
+                       foundry.FromConfig = fromConfig;
+                       InternalRegister (foundryName, foundry, fromConfig);
                }               
 
                void RegisterConfigControls ()
@@ -142,25 +201,25 @@ namespace System.Web.Compilation
                        Assembly asm;
                        foreach (TagPrefixInfo tpi in controls) {
                                if (!String.IsNullOrEmpty (tpi.TagName))
-                                       RegisterFoundry (tpi.TagPrefix, tpi.TagName, tpi.Source);
+                                       RegisterFoundry (tpi.TagPrefix, tpi.TagName, tpi.Source, true);
                                else if (String.IsNullOrEmpty (tpi.Assembly)) {
                                        if (haveCodeAssemblies) {
                                                foreach (object o in appCode) {
                                                        asm = o as Assembly;
                                                        if (asm == null)
                                                                continue;
-                                                       RegisterFoundry (tpi.TagPrefix, asm, tpi.Namespace);
+                                                       RegisterFoundry (tpi.TagPrefix, asm, tpi.Namespace, true);
                                                }
                                        }
                                } else if (!String.IsNullOrEmpty (tpi.Namespace))
                                        RegisterAssemblyFoundry (tpi.TagPrefix,
                                                                 tpi.Assembly,
-                                                                tpi.Namespace);
+                                                                tpi.Namespace,
+                                                                true);
                        }
                }
-#endif
                
-               void InternalRegister (string foundryName, Foundry foundry)
+               void InternalRegister (string foundryName, Foundry foundry, bool fromConfig)
                {
                        object f = foundries [foundryName];
                        Foundry newFoundry = null;
@@ -175,6 +234,7 @@ namespace System.Web.Compilation
                                compound.Add ((Foundry) f);
                                compound.Add (foundry);
                                newFoundry = foundry;
+                               newFoundry.FromConfig = fromConfig;
                        }
 
                        if (newFoundry == null)
@@ -191,8 +251,19 @@ namespace System.Web.Compilation
                                af.Add (f);
                                foundries [foundryName] = af;
                        }
-                       
-                       af.Insert (0, newFoundry);
+
+                       if (newFoundry is AssemblyFoundry) {
+                               object o;
+                               for (int i = 0; i < af.Count; i++) {
+                                       o = af [i];
+                                       if (o is AssemblyFoundry) {
+                                               af.Insert (i, newFoundry);
+                                               return;
+                                       }
+                               }
+                               af.Add (newFoundry);
+                       } else
+                               af.Insert (0, newFoundry);
                }
 
                public bool LookupFoundry (string foundryName)
@@ -202,7 +273,14 @@ namespace System.Web.Compilation
 
                abstract class Foundry
                {
-                       public abstract Type GetType (string componentName);
+                       bool _fromConfig;
+
+                       public bool FromConfig {
+                               get { return _fromConfig; }
+                               set { _fromConfig = value; }
+                       }
+                       
+                       public abstract Type GetType (string componentName, out string source, out string ns);
                }
                
 
@@ -210,8 +288,6 @@ namespace System.Web.Compilation
                {
                        string tagName;
                        Type type;
-
-#if NET_2_0
                        string source;
 
                        public bool FromWebConfig {
@@ -223,7 +299,6 @@ namespace System.Web.Compilation
                                this.tagName = tagName;
                                this.source = source;
                        }
-#endif
                        
                        public TagNameFoundry (string tagName, Type type)
                        {
@@ -231,17 +306,19 @@ namespace System.Web.Compilation
                                this.type = type;
                        }
 
-                       public override Type GetType (string componentName)
+                       public override Type GetType (string componentName, out string source, out string ns)
                        {
-                               if (0 != String.Compare (componentName, tagName, true))
+                               source = null;
+                               ns = null;
+                               if (0 != String.Compare (componentName, tagName, true, Helpers.InvariantCulture))
                                        return null;
 
+                               source = this.source;
                                return LoadType ();
                        }
 
                        Type LoadType ()
                        {
-#if NET_2_0
                                if (type != null)
                                        return type;
 
@@ -267,9 +344,6 @@ namespace System.Web.Compilation
                                        BuildManager.AddToReferencedAssemblies (type.Assembly);
                                }
                                return type;
-#else
-                               return type;
-#endif
                        }
                        
                        public string TagName {
@@ -281,43 +355,39 @@ namespace System.Web.Compilation
                {
                        string nameSpace;
                        Assembly assembly;
-#if NET_2_0
                        string assemblyName;
                        Dictionary <string, Assembly> assemblyCache;
-#endif
                        
                        public AssemblyFoundry (Assembly assembly, string nameSpace)
                        {
                                this.assembly = assembly;
                                this.nameSpace = nameSpace;
-#if NET_2_0
+
                                if (assembly != null)
                                        this.assemblyName = assembly.FullName;
                                else
                                        this.assemblyName = null;
-#endif
                        }
 
-#if NET_2_0
                        public AssemblyFoundry (string assemblyName, string nameSpace)
                        {
                                this.assembly = null;
                                this.nameSpace = nameSpace;
                                this.assemblyName = assemblyName;
                        }
-#endif
                        
-                       public override Type GetType (string componentName)
+                       public override Type GetType (string componentName, out string source, out string ns)
                        {
-#if NET_2_0
+                               source = null;
+                               ns = nameSpace;
+
                                if (assembly == null && assemblyName != null)
                                        assembly = GetAssemblyByName (assemblyName, true);
-#endif
+
                                string typeName = String.Concat (nameSpace, ".", componentName);
                                if (assembly != null)
-                                       return assembly.GetType (typeName, true, true);
+                                       return assembly.GetType (typeName, false, true);
 
-#if NET_2_0
                                IList tla = BuildManager.TopLevelAssemblies;
                                if (tla != null && tla.Count > 0) {
                                        Type ret = null;
@@ -329,11 +399,10 @@ namespace System.Web.Compilation
                                                        return ret;
                                        }
                                }
-#endif
+
                                return null;
                        }
 
-#if NET_2_0
                        Assembly GetAssemblyByName (string name, bool throwOnMissing)
                        {
                                if (assemblyCache == null)
@@ -365,7 +434,6 @@ namespace System.Web.Compilation
                                assemblyCache.Add (name, assembly);
                                return assembly;
                        }
-#endif
                }
 
                class CompoundFoundry : Foundry
@@ -377,12 +445,7 @@ namespace System.Web.Compilation
                        public CompoundFoundry (string tagPrefix)
                        {
                                this.tagPrefix = tagPrefix;
-#if NET_2_0
                                tagnames = new Hashtable (StringComparer.InvariantCultureIgnoreCase);
-#else
-                               tagnames = new Hashtable (CaseInsensitiveHashCodeProvider.DefaultInvariant,
-                                                         CaseInsensitiveComparer.DefaultInvariant);
-#endif
                        }
 
                        public void Add (Foundry foundry)
@@ -395,32 +458,32 @@ namespace System.Web.Compilation
                                TagNameFoundry tn = (TagNameFoundry) foundry;
                                string tagName = tn.TagName;
                                if (tagnames.Contains (tagName)) {
-#if NET_2_0
                                        if (tn.FromWebConfig)
                                                return;
-#endif
+
                                        string msg = String.Format ("{0}:{1} already registered.", tagPrefix, tagName);
                                        throw new ApplicationException (msg);
                                }
                                tagnames.Add (tagName, foundry);
                        }
 
-                       public override Type GetType (string componentName)
+                       public override Type GetType (string componentName, out string source, out string ns)
                        {
+                               source = null;
+                               ns = null;
                                Type type = null;
                                Foundry foundry = tagnames [componentName] as Foundry;
                                if (foundry != null)
-                                       return foundry.GetType (componentName);
+                                       return foundry.GetType (componentName, out source, out ns);
 
                                if (assemblyFoundry != null) {
                                        try {
-                                               type = assemblyFoundry.GetType (componentName);
+                                               type = assemblyFoundry.GetType (componentName, out source, out ns);
                                                return type;
                                        } catch { }
                                }
 
-                               string msg = String.Format ("Type {0} not registered for prefix {1}",
-                                                           componentName, tagPrefix);
+                               string msg = String.Format ("Type {0} not registered for prefix {1}", componentName, tagPrefix);
                                throw new ApplicationException (msg);
                        }
                }