2 // System.Web.Compilation.AspComponentFoundry
5 // Gonzalo Paniagua Javier (gonzalo@ximian.com)
7 // (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
11 // Permission is hereby granted, free of charge, to any person obtaining
12 // a copy of this software and associated documentation files (the
13 // "Software"), to deal in the Software without restriction, including
14 // without limitation the rights to use, copy, modify, merge, publish,
15 // distribute, sublicense, and/or sell copies of the Software, and to
16 // permit persons to whom the Software is furnished to do so, subject to
17 // the following conditions:
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
22 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
23 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
24 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
25 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
26 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
27 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
28 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
31 using System.Collections;
33 using System.Reflection;
36 using System.Collections.Generic;
38 using System.Web.Configuration;
42 namespace System.Web.Compilation
44 internal class AspComponentFoundry
46 private Hashtable foundries;
48 public AspComponentFoundry ()
51 foundries = new Hashtable (StringComparer.InvariantCultureIgnoreCase);
53 foundries = new Hashtable (CaseInsensitiveHashCodeProvider.DefaultInvariant,
54 CaseInsensitiveComparer.DefaultInvariant);
57 Assembly sw = typeof (AspComponentFoundry).Assembly;
58 RegisterFoundry ("asp", sw, "System.Web.UI.WebControls");
59 RegisterFoundry ("", "object", typeof (System.Web.UI.ObjectTag));
62 RegisterConfigControls ();
66 public Type GetComponentType (string foundryName, string tag)
68 Foundry foundry = foundries [foundryName] as Foundry;
72 return foundry.GetType (tag);
75 public void RegisterFoundry (string foundryName,
79 AssemblyFoundry foundry = new AssemblyFoundry (assembly, nameSpace);
80 InternalRegister (foundryName, foundry);
83 public void RegisterFoundry (string foundryName,
87 TagNameFoundry foundry = new TagNameFoundry (tagName, type);
88 InternalRegister (foundryName, foundry);
92 public void RegisterFoundry (string foundryName,
96 TagNameFoundry foundry = new TagNameFoundry (tagName, source);
97 InternalRegister (foundryName, foundry);
100 // Look up the controls/namespaces defined in the config
101 // file(s), resolve the assemblies but do not compile the types.
102 void RegisterConfigControls ()
104 PagesSection pages = WebConfigurationManager.GetSection ("system.web/pages") as PagesSection;
108 TagPrefixCollection controls = pages.Controls;
109 if (controls == null || controls.Count == 0)
112 Dictionary <string, Assembly> assemblyCache = new Dictionary <string, Assembly> ();
113 foreach (TagPrefixInfo tpi in controls) {
114 if (!String.IsNullOrEmpty (tpi.TagName))
115 RegisterFoundry (tpi.TagPrefix, tpi.TagName, tpi.Source);
116 else if (!String.IsNullOrEmpty (tpi.Namespace))
117 RegisterFoundry (tpi.TagPrefix, GetAssemblyByName (assemblyCache, tpi.Assembly), tpi.Namespace);
121 Assembly GetAssemblyByName (Dictionary <string, Assembly> cache, string name)
123 if (cache.ContainsKey (name))
126 Assembly assembly = null;
127 Exception error = null;
128 if (name.IndexOf (',') != -1) {
130 assembly = Assembly.Load (name);
131 } catch (Exception e) { error = e; }
134 if (assembly == null) {
136 assembly = Assembly.LoadWithPartialName (name);
137 } catch (Exception e) { error = e; }
140 if (assembly == null)
141 throw new HttpException ("Assembly " + name + " not found", error);
147 void InternalRegister (string foundryName, Foundry foundry)
149 object f = foundries [foundryName];
150 if (f is CompoundFoundry) {
151 ((CompoundFoundry) f).Add (foundry);
152 } else if (f == null || (f is AssemblyFoundry && foundry is AssemblyFoundry)) {
153 // If more than 1 namespace/assembly specified, the last one is used.
154 foundries [foundryName] = foundry;
155 } else if (f != null) {
156 CompoundFoundry compound = new CompoundFoundry (foundryName);
157 compound.Add ((Foundry) f);
158 compound.Add (foundry);
159 foundries [foundryName] = compound;
163 public bool LookupFoundry (string foundryName)
165 return foundries.Contains (foundryName);
168 abstract class Foundry
170 public abstract Type GetType (string componentName);
174 class TagNameFoundry : Foundry
182 public bool FromWebConfig {
183 get { return source != null; }
186 public TagNameFoundry (string tagName, string source)
188 this.tagName = tagName;
189 this.source = source;
193 public TagNameFoundry (string tagName, Type type)
195 this.tagName = tagName;
199 public override Type GetType (string componentName)
201 if (0 != String.Compare (componentName, tagName, true))
213 HttpContext context = HttpContext.Current;
217 if (VirtualPathUtility.IsAppRelative (source)) {
219 realpath = context.Request.MapPath (source);
221 vpath = VirtualPathUtility.ToAppRelative (source);
225 if ((type = CachingCompiler.GetTypeFromCache (realpath)) != null)
228 ArrayList other_deps = new ArrayList ();
229 type = UserControlParser.GetCompiledType (vpath, realpath, other_deps, context);
231 AspGenerator.AddTypeToCache (other_deps, realpath, type);
232 WebConfigurationManager.ExtraAssemblies.Add (type.Assembly.Location);
240 public string TagName {
241 get { return tagName; }
245 class AssemblyFoundry : Foundry
250 public AssemblyFoundry (Assembly assembly, string nameSpace)
252 this.assembly = assembly;
253 this.nameSpace = nameSpace;
256 public override Type GetType (string componentName)
258 return assembly.GetType (nameSpace + "." + componentName, true, true);
262 class CompoundFoundry : Foundry
264 AssemblyFoundry assemblyFoundry;
268 public CompoundFoundry (string tagPrefix)
270 this.tagPrefix = tagPrefix;
272 tagnames = new Hashtable (StringComparer.InvariantCultureIgnoreCase);
274 tagnames = new Hashtable (CaseInsensitiveHashCodeProvider.DefaultInvariant,
275 CaseInsensitiveComparer.DefaultInvariant);
279 public void Add (Foundry foundry)
281 if (foundry is AssemblyFoundry) {
282 assemblyFoundry = (AssemblyFoundry) foundry;
286 TagNameFoundry tn = (TagNameFoundry) foundry;
287 string tagName = tn.TagName;
288 if (tagnames.Contains (tagName)) {
290 if (tn.FromWebConfig)
293 string msg = String.Format ("{0}:{1} already registered.", tagPrefix, tagName);
294 throw new ApplicationException (msg);
296 tagnames.Add (tagName, foundry);
299 public override Type GetType (string componentName)
302 Foundry foundry = tagnames [componentName] as Foundry;
304 return foundry.GetType (componentName);
306 if (assemblyFoundry != null) {
308 type = assemblyFoundry.GetType (componentName);
313 string msg = String.Format ("Type {0} not registered for prefix {1}",
314 componentName, tagPrefix);
315 throw new ApplicationException (msg);