X-Git-Url: http://wien.tomnetworks.com/gitweb/?a=blobdiff_plain;f=mcs%2Fclass%2FSystem.Web%2FSystem.Web.Compilation%2FAspComponentFoundry.cs;h=cc3268e383301e078c72bfc23d178c0f2da628c1;hb=96b54e28f09a43a3563572024f151ccb7da384bd;hp=c05c719fd66ef6100662c052245a13af1f54b803;hpb=9869ae24b88761ab261c4311e24f7383b4af3f02;p=mono.git diff --git a/mcs/class/System.Web/System.Web.Compilation/AspComponentFoundry.cs b/mcs/class/System.Web/System.Web.Compilation/AspComponentFoundry.cs index c05c719fd66..cc3268e3833 100644 --- a/mcs/class/System.Web/System.Web.Compilation/AspComponentFoundry.cs +++ b/mcs/class/System.Web/System.Web.Compilation/AspComponentFoundry.cs @@ -29,68 +29,241 @@ // 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 { - internal class AspComponentFoundry + class AspComponentFoundry { - private Hashtable foundries; - + Hashtable foundries; + Dictionary components; + Dictionary Components { + get { + if (components == null) + components = new Dictionary (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)); + RegisterConfigControls (); } - public Type GetComponentType (string foundryName, string tag) + public AspComponent GetComponent (string tagName) { - Foundry foundry = foundries [foundryName] as Foundry; - if (foundry == null) + 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; - return foundry.GetType (tag); + 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 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) + Assembly assembly, + 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) + string tagName, + Type type, + bool fromConfig) { TagNameFoundry foundry = new TagNameFoundry (tagName, type); - InternalRegister (foundryName, foundry); + 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); } - void InternalRegister (string foundryName, Foundry foundry) + 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.GetSection ("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); - } else if (f == null || (f is AssemblyFoundry && foundry is AssemblyFoundry)) { - // If more than 1 namespace/assembly specified, the last one is used. - foundries [foundryName] = 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); - foundries [foundryName] = compound; + 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) @@ -100,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); } @@ -108,21 +288,64 @@ namespace System.Web.Compilation { 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) + 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 (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; } } @@ -132,16 +355,84 @@ namespace System.Web.Compilation { string nameSpace; Assembly assembly; - + string assemblyName; + Dictionary 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; } - public override Type GetType (string componentName) + Assembly GetAssemblyByName (string name, bool throwOnMissing) { - return assembly.GetType (nameSpace + "." + componentName, true, true); + if (assemblyCache == null) + assemblyCache = new Dictionary (); + + 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; } } @@ -154,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) @@ -172,31 +458,34 @@ namespace System.Web.Compilation 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) + 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); } } } } -