Mark tests as not working under TARGET_JVM
[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                         IList appCode = BuildManager.CodeAssemblies;
114                         bool haveCodeAssemblies = appCode != null && appCode.Count > 0;
115                         Assembly asm;
116                         foreach (TagPrefixInfo tpi in controls) {
117                                 if (!String.IsNullOrEmpty (tpi.TagName))
118                                         RegisterFoundry (tpi.TagPrefix, tpi.TagName, tpi.Source);
119                                 else if (String.IsNullOrEmpty (tpi.Assembly)) {
120                                         if (haveCodeAssemblies) {
121                                                 foreach (object o in appCode) {
122                                                         asm = o as Assembly;
123                                                         if (asm == null)
124                                                                 continue;
125                                                         RegisterFoundry (tpi.TagPrefix, asm, tpi.Namespace);
126                                                 }
127                                         }
128                                 } else if (!String.IsNullOrEmpty (tpi.Namespace))
129                                         RegisterFoundry (tpi.TagPrefix, GetAssemblyByName (assemblyCache, tpi.Assembly), tpi.Namespace);
130                         }
131                 }
132
133                 Assembly GetAssemblyByName (Dictionary <string, Assembly> cache, string name)
134                 {
135                         if (cache.ContainsKey (name))
136                                 return cache [name];
137
138                         Assembly assembly = null;
139                         Exception error = null;
140                         if (name.IndexOf (',') != -1) {
141                                 try {
142                                         assembly = Assembly.Load (name);
143                                 } catch (Exception e) { error = e; }
144                         }
145
146                         if (assembly == null) {
147                                 try {
148                                         assembly = Assembly.LoadWithPartialName (name);
149                                 } catch (Exception e) { error = e; }
150                         }
151                         
152                         if (assembly == null)
153                                 throw new HttpException ("Assembly " + name + " not found", error);
154
155                         return assembly;
156                 }
157 #endif
158                 
159                 void InternalRegister (string foundryName, Foundry foundry)
160                 {
161                         object f = foundries [foundryName];
162                         if (f is CompoundFoundry) {
163                                 ((CompoundFoundry) f).Add (foundry);
164                         } else if (f == null || (f is AssemblyFoundry && foundry is AssemblyFoundry)) {
165                                 // If more than 1 namespace/assembly specified, the last one is used.
166                                 foundries [foundryName] = foundry;
167                         } else if (f != null) {
168                                 CompoundFoundry compound = new CompoundFoundry (foundryName);
169                                 compound.Add ((Foundry) f);
170                                 compound.Add (foundry);
171                                 foundries [foundryName] = compound;
172                         }
173                 }
174
175                 public bool LookupFoundry (string foundryName)
176                 {
177                         return foundries.Contains (foundryName);
178                 }
179
180                 abstract class Foundry
181                 {
182                         public abstract Type GetType (string componentName);
183                 }
184                 
185
186                 class TagNameFoundry : Foundry
187                 {
188                         string tagName;
189                         Type type;
190
191 #if NET_2_0
192                         string source;
193
194                         public bool FromWebConfig {
195                                 get { return source != null; }
196                         }
197                         
198                         public TagNameFoundry (string tagName, string source)
199                         {
200                                 this.tagName = tagName;
201                                 this.source = source;
202                         }
203 #endif
204                         
205                         public TagNameFoundry (string tagName, Type type)
206                         {
207                                 this.tagName = tagName;
208                                 this.type = type;
209                         }
210
211                         public override Type GetType (string componentName)
212                         {
213                                 if (0 != String.Compare (componentName, tagName, true))
214                                         return null;
215
216                                 return LoadType ();
217                         }
218
219                         Type LoadType ()
220                         {
221 #if NET_2_0
222                                 if (type != null)
223                                         return type;
224
225                                 HttpContext context = HttpContext.Current;
226                                 string vpath;
227                                 string realpath;
228                                 
229                                 if (VirtualPathUtility.IsAppRelative (source)) {
230                                         vpath = source;
231                                         realpath = context.Request.MapPath (source);
232                                 } else {
233                                         vpath = VirtualPathUtility.ToAppRelative (source);
234                                         realpath = source;
235                                 }
236                                 
237                                 if ((type = CachingCompiler.GetTypeFromCache (realpath)) != null)
238                                         return type;
239                                 
240                                 ArrayList other_deps = new ArrayList ();
241                                 type = UserControlParser.GetCompiledType (vpath, realpath, other_deps, context);
242                                 if (type != null) {
243                                         AspGenerator.AddTypeToCache (other_deps, realpath, type);
244                                         WebConfigurationManager.ExtraAssemblies.Add (type.Assembly.Location);
245                                 }
246                                 return type;
247 #else
248                                 return type;
249 #endif
250                         }
251                         
252                         public string TagName {
253                                 get { return tagName; }
254                         }
255                 }
256
257                 class AssemblyFoundry : Foundry
258                 {
259                         string nameSpace;
260                         Assembly assembly;
261
262                         public AssemblyFoundry (Assembly assembly, string nameSpace)
263                         {
264                                 this.assembly = assembly;
265                                 this.nameSpace = nameSpace;
266                         }
267
268                         public override Type GetType (string componentName)
269                         {
270                                 if (assembly != null)
271                                         return assembly.GetType (nameSpace + "." + componentName, true, true);
272                                 return null;
273                         }
274                 }
275
276                 class CompoundFoundry : Foundry
277                 {
278                         AssemblyFoundry assemblyFoundry;
279                         Hashtable tagnames;
280                         string tagPrefix;
281
282                         public CompoundFoundry (string tagPrefix)
283                         {
284                                 this.tagPrefix = tagPrefix;
285 #if NET_2_0
286                                 tagnames = new Hashtable (StringComparer.InvariantCultureIgnoreCase);
287 #else
288                                 tagnames = new Hashtable (CaseInsensitiveHashCodeProvider.DefaultInvariant,
289                                                           CaseInsensitiveComparer.DefaultInvariant);
290 #endif
291                         }
292
293                         public void Add (Foundry foundry)
294                         {
295                                 if (foundry is AssemblyFoundry) {
296                                         assemblyFoundry = (AssemblyFoundry) foundry;
297                                         return;
298                                 }
299                                 
300                                 TagNameFoundry tn = (TagNameFoundry) foundry;
301                                 string tagName = tn.TagName;
302                                 if (tagnames.Contains (tagName)) {
303 #if NET_2_0
304                                         if (tn.FromWebConfig)
305                                                 return;
306 #endif
307                                         string msg = String.Format ("{0}:{1} already registered.", tagPrefix, tagName);
308                                         throw new ApplicationException (msg);
309                                 }
310                                 tagnames.Add (tagName, foundry);
311                         }
312
313                         public override Type GetType (string componentName)
314                         {
315                                 Type type = null;
316                                 Foundry foundry = tagnames [componentName] as Foundry;
317                                 if (foundry != null)
318                                         return foundry.GetType (componentName);
319
320                                 if (assemblyFoundry != null) {
321                                         try {
322                                                 type = assemblyFoundry.GetType (componentName);
323                                                 return type;
324                                         } catch { }
325                                 }
326
327                                 string msg = String.Format ("Type {0} not registered for prefix {1}",
328                                                             componentName, tagPrefix);
329                                 throw new ApplicationException (msg);
330                         }
331                 }
332         }
333 }
334