fixed tests
[mono.git] / mcs / class / System.Web / System.Web.Compilation / AspComponentFoundry.cs
1 //
2 // System.Web.Compilation.AspComponentFoundry
3 //
4 // Authors:
5 //      Gonzalo Paniagua Javier (gonzalo@ximian.com)
6 //
7 // (C) 2002,2003 Ximian, Inc (http://www.ximian.com)
8 //
9
10 //
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:
18 // 
19 // The above copyright notice and this permission notice shall be
20 // included in all copies or substantial portions of the Software.
21 // 
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.
29 //
30 using System;
31 using System.Collections;
32 using System.IO;
33 using System.Reflection;
34
35 #if NET_2_0
36 using System.Collections.Generic;
37 using System.Web;
38 using System.Web.Configuration;
39 using System.Web.UI;
40 #endif
41
42 namespace System.Web.Compilation
43 {
44         internal class AspComponentFoundry
45         {
46                 private Hashtable foundries;
47
48                 public AspComponentFoundry ()
49                 {
50 #if NET_2_0
51                         foundries = new Hashtable (StringComparer.InvariantCultureIgnoreCase);
52 #else
53                         foundries = new Hashtable (CaseInsensitiveHashCodeProvider.DefaultInvariant,
54                                                    CaseInsensitiveComparer.DefaultInvariant);
55 #endif
56
57                         Assembly sw = typeof (AspComponentFoundry).Assembly;
58                         RegisterFoundry ("asp", sw, "System.Web.UI.WebControls");
59                         RegisterFoundry ("", "object", typeof (System.Web.UI.ObjectTag));
60
61 #if NET_2_0
62                         RegisterConfigControls ();
63 #endif
64                 }
65
66                 public Type GetComponentType (string foundryName, string tag)
67                 {
68                         Foundry foundry = foundries [foundryName] as Foundry;
69                         if (foundry == null)
70                                 return null;
71
72                         return foundry.GetType (tag);
73                 }
74
75                 public void RegisterFoundry (string foundryName,
76                                                 Assembly assembly,
77                                                 string nameSpace)
78                 {
79                         AssemblyFoundry foundry = new AssemblyFoundry (assembly, nameSpace);
80                         InternalRegister (foundryName, foundry);
81                 }
82
83                 public void RegisterFoundry (string foundryName,
84                                                 string tagName,
85                                                 Type type)
86                 {
87                         TagNameFoundry foundry = new TagNameFoundry (tagName, type);
88                         InternalRegister (foundryName, foundry);
89                 }
90
91 #if NET_2_0
92                 public void RegisterFoundry (string foundryName,
93                                              string tagName,
94                                              string source)
95                 {
96                         TagNameFoundry foundry = new TagNameFoundry (tagName, source);
97                         InternalRegister (foundryName, foundry);
98                 }
99                 
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 ()
103                 {
104                         PagesSection pages = WebConfigurationManager.GetSection ("system.web/pages") as PagesSection;
105                         if (pages == null)
106                                 return;
107
108                         TagPrefixCollection controls = pages.Controls;
109                         if (controls == null || controls.Count == 0)
110                                 return;
111
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);
118                         }
119                 }
120
121                 Assembly GetAssemblyByName (Dictionary <string, Assembly> cache, string name)
122                 {
123                         if (cache.ContainsKey (name))
124                                 return cache [name];
125
126                         Assembly assembly = null;
127                         Exception error = null;
128                         if (name.IndexOf (',') != -1) {
129                                 try {
130                                         assembly = Assembly.Load (name);
131                                 } catch (Exception e) { error = e; }
132                         }
133
134                         if (assembly == null) {
135                                 try {
136                                         assembly = Assembly.LoadWithPartialName (name);
137                                 } catch (Exception e) { error = e; }
138                         }
139                         
140                         if (assembly == null)
141                                 throw new HttpException ("Assembly " + name + " not found", error);
142
143                         return assembly;
144                 }
145 #endif
146                 
147                 void InternalRegister (string foundryName, Foundry foundry)
148                 {
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;
160                         }
161                 }
162
163                 public bool LookupFoundry (string foundryName)
164                 {
165                         return foundries.Contains (foundryName);
166                 }
167
168                 abstract class Foundry
169                 {
170                         public abstract Type GetType (string componentName);
171                 }
172                 
173
174                 class TagNameFoundry : Foundry
175                 {
176                         string tagName;
177                         Type type;
178
179 #if NET_2_0
180                         string source;
181
182                         public bool FromWebConfig {
183                                 get { return source != null; }
184                         }
185                         
186                         public TagNameFoundry (string tagName, string source)
187                         {
188                                 this.tagName = tagName;
189                                 this.source = source;
190                         }
191 #endif
192                         
193                         public TagNameFoundry (string tagName, Type type)
194                         {
195                                 this.tagName = tagName;
196                                 this.type = type;
197                         }
198
199                         public override Type GetType (string componentName)
200                         {
201                                 if (0 != String.Compare (componentName, tagName, true))
202                                         return null;
203
204                                 return LoadType ();
205                         }
206
207                         Type LoadType ()
208                         {
209 #if NET_2_0
210                                 if (type != null)
211                                         return type;
212
213                                 HttpContext context = HttpContext.Current;
214                                 string vpath;
215                                 string realpath;
216                                 
217                                 if (VirtualPathUtility.IsAppRelative (source)) {
218                                         vpath = source;
219                                         realpath = context.Request.MapPath (source);
220                                 } else {
221                                         vpath = VirtualPathUtility.ToAppRelative (source);
222                                         realpath = source;
223                                 }
224                                 
225                                 if ((type = CachingCompiler.GetTypeFromCache (realpath)) != null)
226                                         return type;
227                                 
228                                 ArrayList other_deps = new ArrayList ();
229                                 type = UserControlParser.GetCompiledType (vpath, realpath, other_deps, context);
230                                 if (type != null) {
231                                         AspGenerator.AddTypeToCache (other_deps, realpath, type);
232                                         WebConfigurationManager.ExtraAssemblies.Add (type.Assembly.Location);
233                                 }
234                                 return type;
235 #else
236                                 return type;
237 #endif
238                         }
239                         
240                         public string TagName {
241                                 get { return tagName; }
242                         }
243                 }
244
245                 class AssemblyFoundry : Foundry
246                 {
247                         string nameSpace;
248                         Assembly assembly;
249
250                         public AssemblyFoundry (Assembly assembly, string nameSpace)
251                         {
252                                 this.assembly = assembly;
253                                 this.nameSpace = nameSpace;
254                         }
255
256                         public override Type GetType (string componentName)
257                         {
258                                 return assembly.GetType (nameSpace + "." + componentName, true, true);
259                         }
260                 }
261
262                 class CompoundFoundry : Foundry
263                 {
264                         AssemblyFoundry assemblyFoundry;
265                         Hashtable tagnames;
266                         string tagPrefix;
267
268                         public CompoundFoundry (string tagPrefix)
269                         {
270                                 this.tagPrefix = tagPrefix;
271 #if NET_2_0
272                                 tagnames = new Hashtable (StringComparer.InvariantCultureIgnoreCase);
273 #else
274                                 tagnames = new Hashtable (CaseInsensitiveHashCodeProvider.DefaultInvariant,
275                                                           CaseInsensitiveComparer.DefaultInvariant);
276 #endif
277                         }
278
279                         public void Add (Foundry foundry)
280                         {
281                                 if (foundry is AssemblyFoundry) {
282                                         assemblyFoundry = (AssemblyFoundry) foundry;
283                                         return;
284                                 }
285                                 
286                                 TagNameFoundry tn = (TagNameFoundry) foundry;
287                                 string tagName = tn.TagName;
288                                 if (tagnames.Contains (tagName)) {
289 #if NET_2_0
290                                         if (tn.FromWebConfig)
291                                                 return;
292 #endif
293                                         string msg = String.Format ("{0}:{1} already registered.", tagPrefix, tagName);
294                                         throw new ApplicationException (msg);
295                                 }
296                                 tagnames.Add (tagName, foundry);
297                         }
298
299                         public override Type GetType (string componentName)
300                         {
301                                 Type type = null;
302                                 Foundry foundry = tagnames [componentName] as Foundry;
303                                 if (foundry != null)
304                                         return foundry.GetType (componentName);
305
306                                 if (assemblyFoundry != null) {
307                                         try {
308                                                 type = assemblyFoundry.GetType (componentName);
309                                                 return type;
310                                         } catch { }
311                                 }
312
313                                 string msg = String.Format ("Type {0} not registered for prefix {1}",
314                                                             componentName, tagPrefix);
315                                 throw new ApplicationException (msg);
316                         }
317                 }
318         }
319 }
320