-//\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);
+ }
+ }
+ }
+}