More 1.1 code and NET_2_0 ifdefs removed
[mono.git] / mcs / class / System.Web / System.Web.Compilation / AspComponentFoundry.cs
index af0b8b6e92d2d7ce3dde558bc3cf12975d45457b..97d9e1becd8b1a552b201ada1dbbfb09ac01a9b1 100644 (file)
@@ -1,11 +1,11 @@
-//\r
-// System.Web.Compilation.AspComponentFoundry\r
-//\r
-// Authors:\r
-//     Gonzalo Paniagua Javier (gonzalo@ximian.com)\r
-//\r
-// (C) 2002,2003 Ximian, Inc (http://www.ximian.com)\r
-//\r
+//
+// System.Web.Compilation.AspComponentFoundry
+//
+// Authors:
+//     Gonzalo Paniagua Javier (gonzalo@ximian.com)
+//
+// (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
+//
 
 //
 // Permission is hereby granted, free of charge, to any person obtaining
 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 //
-using System;\r
-using System.Collections;\r
-using System.IO;\r
-using System.Reflection;\r
-\r
-namespace System.Web.Compilation\r
-{\r
-       internal class AspComponentFoundry\r
-       {\r
-               private Hashtable foundries;\r
-\r
-               public AspComponentFoundry ()\r
-               {\r
-                       foundries = new Hashtable (CaseInsensitiveHashCodeProvider.Default,\r
-                                                  CaseInsensitiveComparer.Default);\r
-\r
-                       Assembly sw = typeof (AspComponentFoundry).Assembly;\r
-                       RegisterFoundry ("asp", sw, "System.Web.UI.WebControls");\r
-                       RegisterFoundry ("", "object", typeof (System.Web.UI.ObjectTag));\r
-               }\r
-\r
-               public Type GetComponentType (string foundryName, string tag)\r
-               {\r
-                       Foundry foundry = foundries [foundryName] as Foundry;\r
-                       if (foundry == null)\r
-                               return null;\r
-\r
-                       return foundry.GetType (tag);\r
-               }\r
-\r
-               public void RegisterFoundry (string foundryName,\r
-                                               Assembly assembly,\r
-                                               string nameSpace)\r
-               {\r
-                       AssemblyFoundry foundry = new AssemblyFoundry (assembly, nameSpace);\r
-                       InternalRegister (foundryName, foundry);\r
-               }\r
-\r
-               public void RegisterFoundry (string foundryName,\r
-                                               string tagName,\r
-                                               Type type)\r
-               {\r
-                       TagNameFoundry foundry = new TagNameFoundry (tagName, type);\r
-                       InternalRegister (foundryName, foundry);\r
-               }\r
-\r
-               void InternalRegister (string foundryName, Foundry foundry)\r
-               {\r
-                       object f = foundries [foundryName];\r
-                       if (f is CompoundFoundry) {\r
-                               ((CompoundFoundry) f).Add (foundry);\r
-                       } else if (f == null || (f is AssemblyFoundry && foundry is AssemblyFoundry)) {\r
-                               // If more than 1 namespace/assembly specified, the last one is used.\r
-                               foundries [foundryName] = foundry;\r
-                       } else if (f != null) {\r
-                               CompoundFoundry compound = new CompoundFoundry (foundryName);\r
-                               compound.Add ((Foundry) f);\r
-                               compound.Add (foundry);\r
-                               foundries [foundryName] = compound;\r
-                       }\r
-               }\r
-\r
-               public bool LookupFoundry (string foundryName)\r
-               {\r
-                       return foundries.Contains (foundryName);\r
-               }\r
-\r
-               abstract class Foundry\r
-               {\r
-                       public abstract Type GetType (string componentName);\r
-               }\r
-               \r
-\r
-               class TagNameFoundry : Foundry\r
-               {\r
-                       string tagName;\r
-                       Type type;\r
-\r
-                       public TagNameFoundry (string tagName, Type type)\r
-                       {\r
-                               this.tagName = tagName;\r
-                               this.type = type;\r
-                       }\r
-\r
-                       public override Type GetType (string componentName)\r
-                       {\r
-                               if (0 != String.Compare (componentName, tagName, true))\r
-                                       return null;\r
-                               \r
-                               return type;\r
-                       }\r
-\r
-                       public string TagName {\r
-                               get { return tagName; }\r
-                       }\r
-               }\r
-\r
-               class AssemblyFoundry : Foundry\r
-               {\r
-                       string nameSpace;\r
-                       Assembly assembly;\r
-\r
-                       public AssemblyFoundry (Assembly assembly, string nameSpace)\r
-                       {\r
-                               this.assembly = assembly;\r
-                               this.nameSpace = nameSpace;\r
-                       }\r
-\r
-                       public override Type GetType (string componentName)\r
-                       {\r
-                               return assembly.GetType (nameSpace + "." + componentName, true, true);\r
-                       }\r
-               }\r
-\r
-               class CompoundFoundry : Foundry\r
-               {\r
-                       AssemblyFoundry assemblyFoundry;\r
-                       Hashtable tagnames;\r
-                       string tagPrefix;\r
-\r
-                       public CompoundFoundry (string tagPrefix)\r
-                       {\r
-                               this.tagPrefix = tagPrefix;\r
-                               tagnames = new Hashtable (CaseInsensitiveHashCodeProvider.Default,\r
-                                                          CaseInsensitiveComparer.Default);\r
-                       }\r
-\r
-                       public void Add (Foundry foundry)\r
-                       {\r
-                               if (foundry is AssemblyFoundry) {\r
-                                       assemblyFoundry = (AssemblyFoundry) foundry;\r
-                                       return;\r
-                               }\r
-                               \r
-                               TagNameFoundry tn = (TagNameFoundry) foundry;\r
-                               string tagName = tn.TagName;\r
-                               if (tagnames.Contains (tagName)) {\r
-                                       string msg = String.Format ("{0}:{1} already registered.", tagPrefix, tagName);\r
-                                       throw new ApplicationException (msg);\r
-                               }\r
-                               tagnames.Add (tagName, foundry);\r
-                       }\r
-\r
-                       public override Type GetType (string componentName)\r
-                       {\r
-                               Type type = null;\r
-                               if (assemblyFoundry != null) {\r
-                                       try {\r
-                                               type = assemblyFoundry.GetType (componentName);\r
-                                               return type;\r
-                                       } catch { }\r
-                               }\r
-\r
-                               Foundry foundry = tagnames [componentName] as Foundry;\r
-                               if (foundry == null) {\r
-                                       string msg = String.Format ("Type {0} not registered for prefix {1}",\r
-                                                                    componentName, tagPrefix);\r
-                                       throw new ApplicationException (msg);\r
-                               }\r
-\r
-                               return foundry.GetType (componentName);\r
-                       }\r
-               }\r
-       }\r
-}\r
-\r
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Globalization;
+using System.IO;
+using System.Reflection;
+using System.Web;
+using System.Web.Configuration;
+using System.Web.UI;
+using System.Web.Util;
+
+namespace System.Web.Compilation
+{
+       class AspComponentFoundry
+       {
+               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 ()
+               {
+                       foundries = new Hashtable (StringComparer.InvariantCultureIgnoreCase);
+                       Assembly sw = typeof (AspComponentFoundry).Assembly;
+                       RegisterFoundry ("asp", sw, "System.Web.UI.WebControls");
+                       RegisterFoundry ("", "object", typeof (System.Web.UI.ObjectTag));
+                       RegisterConfigControls ();
+               }
+
+               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;
+                       }
+
+                       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;
+
+                       AspComponent component = null;
+                       Exception e = null;
+                       foreach (Foundry f in af) {
+                               try {
+                                       component = CreateComponent (f, tagName, foundryName, tag);
+                                       if (component != null)
+                                               return component;
+                               } catch (Exception ex) {
+                                       e = ex;
+                               }
+                       }
+
+                       if (e != null)
+                               throw e;
+                       
+                       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,
+                                            bool fromConfig)
+               {
+                       AssemblyFoundry foundry = new AssemblyFoundry (assembly, nameSpace);
+                       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,
+                                            bool fromConfig)
+               {
+                       TagNameFoundry foundry = new TagNameFoundry (tagName, type);
+                       foundry.FromConfig = fromConfig;
+                       InternalRegister (foundryName, foundry, fromConfig);
+               }
+
+               public void RegisterFoundry (string foundryName, string tagName, string source)
+               {
+                       RegisterFoundry (foundryName, tagName, source, false);
+               }
+               
+               public void RegisterFoundry (string foundryName,
+                                            string tagName,
+                                            string source,
+                                            bool fromConfig)
+               {
+                       TagNameFoundry foundry = new TagNameFoundry (tagName, source);
+                       foundry.FromConfig = fromConfig;
+                       InternalRegister (foundryName, foundry, fromConfig);
+               }
+
+               public void RegisterAssemblyFoundry (string foundryName,
+                                                    string assemblyName,
+                                                    string nameSpace,
+                                                    bool fromConfig)
+               {
+                       AssemblyFoundry foundry = new AssemblyFoundry (assemblyName, nameSpace);
+                       foundry.FromConfig = fromConfig;
+                       InternalRegister (foundryName, foundry, fromConfig);
+               }               
+
+               void RegisterConfigControls ()
+               {
+                       PagesSection pages = WebConfigurationManager.GetWebApplicationSection ("system.web/pages") as PagesSection;
+                       if (pages == null)
+                               return;
+
+                       TagPrefixCollection controls = pages.Controls;
+                       if (controls == null || controls.Count == 0)
+                               return;
+                       
+                       IList appCode = BuildManager.CodeAssemblies;
+                       bool haveCodeAssemblies = appCode != null && appCode.Count > 0;
+                       Assembly asm;
+                       foreach (TagPrefixInfo tpi in controls) {
+                               if (!String.IsNullOrEmpty (tpi.TagName))
+                                       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, true);
+                                               }
+                                       }
+                               } else if (!String.IsNullOrEmpty (tpi.Namespace))
+                                       RegisterAssemblyFoundry (tpi.TagPrefix,
+                                                                tpi.Assembly,
+                                                                tpi.Namespace,
+                                                                true);
+                       }
+               }
+               
+               void InternalRegister (string foundryName, Foundry foundry, bool fromConfig)
+               {
+                       object f = foundries [foundryName];
+                       Foundry newFoundry = null;
+                       
+                       if (f is CompoundFoundry) {
+                               ((CompoundFoundry) f).Add (foundry);
+                               return;
+                       } else if (f == null || f is ArrayList || (f is AssemblyFoundry && foundry is AssemblyFoundry)) {
+                               newFoundry = foundry;
+                       } else if (f != null) {
+                               CompoundFoundry compound = new CompoundFoundry (foundryName);
+                               compound.Add ((Foundry) f);
+                               compound.Add (foundry);
+                               newFoundry = foundry;
+                               newFoundry.FromConfig = fromConfig;
+                       }
+
+                       if (newFoundry == null)
+                               return;
+
+                       if (f == null) {
+                               foundries [foundryName] = newFoundry;
+                               return;
+                       }
+
+                       ArrayList af = f as ArrayList;
+                       if (af == null) {
+                               af = new ArrayList (2);
+                               af.Add (f);
+                               foundries [foundryName] = af;
+                       }
+
+                       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)
+               {
+                       return foundries.Contains (foundryName);
+               }
+
+               abstract class Foundry
+               {
+                       bool _fromConfig;
+
+                       public bool FromConfig {
+                               get { return _fromConfig; }
+                               set { _fromConfig = value; }
+                       }
+                       
+                       public abstract Type GetType (string componentName, out string source, out string ns);
+               }
+               
+
+               class TagNameFoundry : Foundry
+               {
+                       string tagName;
+                       Type type;
+                       string source;
+
+                       public bool FromWebConfig {
+                               get { return source != null; }
+                       }
+                       
+                       public TagNameFoundry (string tagName, string source)
+                       {
+                               this.tagName = tagName;
+                               this.source = source;
+                       }
+                       
+                       public TagNameFoundry (string tagName, Type type)
+                       {
+                               this.tagName = tagName;
+                               this.type = type;
+                       }
+
+                       public override Type GetType (string componentName, out string source, out string ns)
+                       {
+                               source = null;
+                               ns = null;
+                               if (0 != String.Compare (componentName, tagName, true, Helpers.InvariantCulture))
+                                       return null;
+
+                               source = this.source;
+                               return LoadType ();
+                       }
+
+                       Type LoadType ()
+                       {
+                               if (type != null)
+                                       return type;
+
+                               HttpContext context = HttpContext.Current;
+                               string vpath;
+                               string realpath;
+                               
+                               if (VirtualPathUtility.IsAppRelative (source)) {
+                                       vpath = source;
+                                       realpath = context.Request.MapPath (source);
+                               } else {
+                                       vpath = VirtualPathUtility.ToAppRelative (source);
+                                       realpath = source;
+                               }
+                               
+                               if ((type = CachingCompiler.GetTypeFromCache (realpath)) != null)
+                                       return type;
+                               
+                               ArrayList other_deps = new ArrayList ();
+                               type = BuildManager.GetCompiledType (vpath);
+                               if (type != null) {
+                                       AspGenerator.AddTypeToCache (other_deps, realpath, type);
+                                       BuildManager.AddToReferencedAssemblies (type.Assembly);
+                               }
+                               return type;
+                       }
+                       
+                       public string TagName {
+                               get { return tagName; }
+                       }
+               }
+
+               class AssemblyFoundry : Foundry
+               {
+                       string nameSpace;
+                       Assembly assembly;
+                       string assemblyName;
+                       Dictionary <string, Assembly> assemblyCache;
+                       
+                       public AssemblyFoundry (Assembly assembly, string nameSpace)
+                       {
+                               this.assembly = assembly;
+                               this.nameSpace = nameSpace;
+
+                               if (assembly != null)
+                                       this.assemblyName = assembly.FullName;
+                               else
+                                       this.assemblyName = null;
+                       }
+
+                       public AssemblyFoundry (string assemblyName, string nameSpace)
+                       {
+                               this.assembly = null;
+                               this.nameSpace = nameSpace;
+                               this.assemblyName = assemblyName;
+                       }
+                       
+                       public override Type GetType (string componentName, out string source, out string ns)
+                       {
+                               source = null;
+                               ns = nameSpace;
+
+                               if (assembly == null && assemblyName != null)
+                                       assembly = GetAssemblyByName (assemblyName, true);
+
+                               string typeName = String.Concat (nameSpace, ".", componentName);
+                               if (assembly != null)
+                                       return assembly.GetType (typeName, false, true);
+
+                               IList tla = BuildManager.TopLevelAssemblies;
+                               if (tla != null && tla.Count > 0) {
+                                       Type ret = null;
+                                       foreach (Assembly asm in tla) {
+                                               if (asm == null)
+                                                       continue;
+                                               ret = asm.GetType (typeName, false, true);
+                                               if (ret != null)
+                                                       return ret;
+                                       }
+                               }
+
+                               return null;
+                       }
+
+                       Assembly GetAssemblyByName (string name, bool throwOnMissing)
+                       {
+                               if (assemblyCache == null)
+                                       assemblyCache = new Dictionary <string, Assembly> ();
+                               
+                               if (assemblyCache.ContainsKey (name))
+                                       return assemblyCache [name];
+                               
+                               Assembly assembly = null;
+                               Exception error = null;
+                               if (name.IndexOf (',') != -1) {
+                                       try {
+                                               assembly = Assembly.Load (name);
+                                       } catch (Exception e) { error = e; }
+                               }
+
+                               if (assembly == null) {
+                                       try {
+                                               assembly = Assembly.LoadWithPartialName (name);
+                                       } catch (Exception e) { error = e; }
+                               }
+                       
+                               if (assembly == null)
+                                       if (throwOnMissing)
+                                               throw new HttpException ("Assembly " + name + " not found", error);
+                                       else
+                                               return null;
+
+                               assemblyCache.Add (name, assembly);
+                               return assembly;
+                       }
+               }
+
+               class CompoundFoundry : Foundry
+               {
+                       AssemblyFoundry assemblyFoundry;
+                       Hashtable tagnames;
+                       string tagPrefix;
+
+                       public CompoundFoundry (string tagPrefix)
+                       {
+                               this.tagPrefix = tagPrefix;
+                               tagnames = new Hashtable (StringComparer.InvariantCultureIgnoreCase);
+                       }
+
+                       public void Add (Foundry foundry)
+                       {
+                               if (foundry is AssemblyFoundry) {
+                                       assemblyFoundry = (AssemblyFoundry) foundry;
+                                       return;
+                               }
+                               
+                               TagNameFoundry tn = (TagNameFoundry) foundry;
+                               string tagName = tn.TagName;
+                               if (tagnames.Contains (tagName)) {
+                                       if (tn.FromWebConfig)
+                                               return;
+
+                                       string msg = String.Format ("{0}:{1} already registered.", tagPrefix, tagName);
+                                       throw new ApplicationException (msg);
+                               }
+                               tagnames.Add (tagName, foundry);
+                       }
+
+                       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, out source, out ns);
+
+                               if (assemblyFoundry != null) {
+                                       try {
+                                               type = assemblyFoundry.GetType (componentName, out source, out ns);
+                                               return type;
+                                       } catch { }
+                               }
+
+                               string msg = String.Format ("Type {0} not registered for prefix {1}", componentName, tagPrefix);
+                               throw new ApplicationException (msg);
+                       }
+               }
+       }
+}