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 object o = foundries [foundryName];
73 return ((Foundry)o).GetType (tag);
75 ArrayList af = o as ArrayList;
81 foreach (Foundry f in af) {
86 } catch (Exception ex) {
97 public void RegisterFoundry (string foundryName,
101 AssemblyFoundry foundry = new AssemblyFoundry (assembly, nameSpace);
102 InternalRegister (foundryName, foundry);
105 public void RegisterFoundry (string foundryName,
109 TagNameFoundry foundry = new TagNameFoundry (tagName, type);
110 InternalRegister (foundryName, foundry);
114 public void RegisterFoundry (string foundryName,
118 TagNameFoundry foundry = new TagNameFoundry (tagName, source);
119 InternalRegister (foundryName, foundry);
122 public void RegisterAssemblyFoundry (string foundryName,
126 AssemblyFoundry foundry = new AssemblyFoundry (assemblyName, nameSpace);
127 InternalRegister (foundryName, foundry);
130 void RegisterConfigControls ()
132 PagesSection pages = WebConfigurationManager.GetSection ("system.web/pages") as PagesSection;
136 TagPrefixCollection controls = pages.Controls;
137 if (controls == null || controls.Count == 0)
140 IList appCode = BuildManager.CodeAssemblies;
141 bool haveCodeAssemblies = appCode != null && appCode.Count > 0;
143 foreach (TagPrefixInfo tpi in controls) {
144 if (!String.IsNullOrEmpty (tpi.TagName))
145 RegisterFoundry (tpi.TagPrefix, tpi.TagName, tpi.Source);
146 else if (String.IsNullOrEmpty (tpi.Assembly)) {
147 if (haveCodeAssemblies) {
148 foreach (object o in appCode) {
152 RegisterFoundry (tpi.TagPrefix, asm, tpi.Namespace);
155 } else if (!String.IsNullOrEmpty (tpi.Namespace))
156 RegisterAssemblyFoundry (tpi.TagPrefix,
163 void InternalRegister (string foundryName, Foundry foundry)
165 object f = foundries [foundryName];
166 Foundry newFoundry = null;
168 if (f is CompoundFoundry) {
169 ((CompoundFoundry) f).Add (foundry);
171 } else if (f == null || f is ArrayList || (f is AssemblyFoundry && foundry is AssemblyFoundry)) {
172 newFoundry = foundry;
173 } else if (f != null) {
174 CompoundFoundry compound = new CompoundFoundry (foundryName);
175 compound.Add ((Foundry) f);
176 compound.Add (foundry);
177 newFoundry = foundry;
180 if (newFoundry == null)
184 foundries [foundryName] = newFoundry;
188 ArrayList af = f as ArrayList;
190 af = new ArrayList (2);
192 foundries [foundryName] = af;
195 af.Insert (0, newFoundry);
198 public bool LookupFoundry (string foundryName)
200 return foundries.Contains (foundryName);
203 abstract class Foundry
205 public abstract Type GetType (string componentName);
209 class TagNameFoundry : Foundry
217 public bool FromWebConfig {
218 get { return source != null; }
221 public TagNameFoundry (string tagName, string source)
223 this.tagName = tagName;
224 this.source = source;
228 public TagNameFoundry (string tagName, Type type)
230 this.tagName = tagName;
234 public override Type GetType (string componentName)
236 if (0 != String.Compare (componentName, tagName, true))
248 HttpContext context = HttpContext.Current;
252 if (VirtualPathUtility.IsAppRelative (source)) {
254 realpath = context.Request.MapPath (source);
256 vpath = VirtualPathUtility.ToAppRelative (source);
260 if ((type = CachingCompiler.GetTypeFromCache (realpath)) != null)
263 ArrayList other_deps = new ArrayList ();
264 type = UserControlParser.GetCompiledType (vpath, realpath, other_deps, context);
266 AspGenerator.AddTypeToCache (other_deps, realpath, type);
267 WebConfigurationManager.ExtraAssemblies.Add (type.Assembly.Location);
275 public string TagName {
276 get { return tagName; }
280 class AssemblyFoundry : Foundry
286 Dictionary <string, Assembly> assemblyCache;
289 public AssemblyFoundry (Assembly assembly, string nameSpace)
291 this.assembly = assembly;
292 this.nameSpace = nameSpace;
294 if (assembly != null)
295 this.assemblyName = assembly.FullName;
297 this.assemblyName = null;
302 public AssemblyFoundry (string assemblyName, string nameSpace)
304 this.assembly = null;
305 this.nameSpace = nameSpace;
306 this.assemblyName = assemblyName;
310 public override Type GetType (string componentName)
313 if (assembly == null && assemblyName != null)
314 assembly = GetAssemblyByName (assemblyName, true);
316 string typeName = String.Concat (nameSpace, ".", componentName);
317 if (assembly != null)
318 return assembly.GetType (typeName, true, true);
321 IList tla = BuildManager.TopLevelAssemblies;
322 if (tla != null && tla.Count > 0) {
324 foreach (Assembly asm in tla) {
327 ret = asm.GetType (typeName, false, true);
337 Assembly GetAssemblyByName (string name, bool throwOnMissing)
339 if (assemblyCache == null)
340 assemblyCache = new Dictionary <string, Assembly> ();
342 if (assemblyCache.ContainsKey (name))
343 return assemblyCache [name];
345 Assembly assembly = null;
346 Exception error = null;
347 if (name.IndexOf (',') != -1) {
349 assembly = Assembly.Load (name);
350 } catch (Exception e) { error = e; }
353 if (assembly == null) {
355 assembly = Assembly.LoadWithPartialName (name);
356 } catch (Exception e) { error = e; }
359 if (assembly == null)
361 throw new HttpException ("Assembly " + name + " not found", error);
365 assemblyCache.Add (name, assembly);
371 class CompoundFoundry : Foundry
373 AssemblyFoundry assemblyFoundry;
377 public CompoundFoundry (string tagPrefix)
379 this.tagPrefix = tagPrefix;
381 tagnames = new Hashtable (StringComparer.InvariantCultureIgnoreCase);
383 tagnames = new Hashtable (CaseInsensitiveHashCodeProvider.DefaultInvariant,
384 CaseInsensitiveComparer.DefaultInvariant);
388 public void Add (Foundry foundry)
390 if (foundry is AssemblyFoundry) {
391 assemblyFoundry = (AssemblyFoundry) foundry;
395 TagNameFoundry tn = (TagNameFoundry) foundry;
396 string tagName = tn.TagName;
397 if (tagnames.Contains (tagName)) {
399 if (tn.FromWebConfig)
402 string msg = String.Format ("{0}:{1} already registered.", tagPrefix, tagName);
403 throw new ApplicationException (msg);
405 tagnames.Add (tagName, foundry);
408 public override Type GetType (string componentName)
411 Foundry foundry = tagnames [componentName] as Foundry;
413 return foundry.GetType (componentName);
415 if (assemblyFoundry != null) {
417 type = assemblyFoundry.GetType (componentName);
422 string msg = String.Format ("Type {0} not registered for prefix {1}",
423 componentName, tagPrefix);
424 throw new ApplicationException (msg);