2007-05-06 Igor Zelmanovich <igorz@mainsoft.com>
[mono.git] / mcs / class / System.Web / System.Web.Configuration_2.0 / HttpHandlerAction.cs
index 0872827329219ca6fcfaff3506444f4fcc952078..cff9ad214dd4d08fd357537a4aeb0b5125e25333 100644 (file)
 #if NET_2_0
 
 using System;
+using System.Collections;
+using System.ComponentModel;
 using System.Configuration;
+using System.Reflection;
+using System.Text.RegularExpressions;
+using System.Web.Util;
 
 namespace System.Web.Configuration
 {
@@ -46,11 +51,18 @@ namespace System.Web.Configuration
                static HttpHandlerAction ()
                {
                        pathProp = new ConfigurationProperty ("path", typeof (string), null,
+                                                             TypeDescriptor.GetConverter (typeof (string)),
+                                                             PropertyHelper.NonEmptyStringValidator,
                                                              ConfigurationPropertyOptions.IsRequired | ConfigurationPropertyOptions.IsKey);
                        typeProp = new ConfigurationProperty ("type", typeof (string), null,
+                                                             TypeDescriptor.GetConverter (typeof (string)),
+                                                             PropertyHelper.NonEmptyStringValidator,
                                                              ConfigurationPropertyOptions.IsRequired);
                        validateProp = new ConfigurationProperty ("validate", typeof (bool), true);
-                       verbProp = new ConfigurationProperty ("verb", typeof (string), null, ConfigurationPropertyOptions.IsRequired);
+                       verbProp = new ConfigurationProperty ("verb", typeof (string), null,
+                                                             TypeDescriptor.GetConverter (typeof (string)),
+                                                             PropertyHelper.NonEmptyStringValidator,\r
+                                                             ConfigurationPropertyOptions.IsRequired | ConfigurationPropertyOptions.IsKey);
 
                        _properties = new ConfigurationPropertyCollection ();
                        _properties.Add (pathProp);
@@ -59,6 +71,9 @@ namespace System.Web.Configuration
                        _properties.Add (verbProp);
                }
 
+               internal HttpHandlerAction ()
+               { }
+
                public HttpHandlerAction (string path, string type, string verb)
                        : this (path, type, verb, true)
                { }
@@ -72,12 +87,14 @@ namespace System.Web.Configuration
                }
 
                [ConfigurationProperty ("path", Options = ConfigurationPropertyOptions.IsRequired | ConfigurationPropertyOptions.IsKey)]
+               // LAMESPEC: MS lists no validator here but provides one in Properties.
                public string Path {
                        get { return (string) base[pathProp]; }
                        set { base[pathProp] = value; }
                }
 
                [ConfigurationProperty ("type", Options = ConfigurationPropertyOptions.IsRequired)]
+               // LAMESPEC: MS lists no validator here but provides one in Properties.
                public string Type {
                        get { return (string) base[typeProp]; }
                        set { base[typeProp] = value; }
@@ -90,16 +107,173 @@ namespace System.Web.Configuration
                }
 
                [ConfigurationProperty ("verb", Options = ConfigurationPropertyOptions.IsRequired | ConfigurationPropertyOptions.IsKey)]
+               // LAMESPEC: MS lists no validator here but provides one in Properties.
                public string Verb {
                        get { return (string) base[verbProp]; }
                        set { base[verbProp] = value; }
                }
 
                protected override ConfigurationPropertyCollection Properties {
+                       get { return _properties; }
+               }
+
+#region CompatabilityCode
+               object instance;
+               Type type;
+
+               string cached_verb = null;
+               string[] cached_verbs;
+
+               string cached_path = null;
+               FileMatchingInfo[] cached_files;
+
+               FileMatchingInfo[] SplitPaths ()
+               {
+                       string [] paths = Path.Split (',');
+                       cached_files = new FileMatchingInfo [paths.Length];
+
+                       int i = 0;
+                       foreach (string s in paths)
+                               cached_files [i++] = new FileMatchingInfo (s);
+
+                       return cached_files;
+               }
+
+               string[] SplitVerbs ()
+               {
+                       if (Verb == "*")
+                               cached_verbs = null;
+                       else
+                               cached_verbs = Verb.Split (',');
+
+                       return cached_verbs;
+               }
+
+               internal string[] Verbs {
+                       get {
+                               if (cached_verb != Verb) {
+                                       cached_verbs = SplitVerbs();
+                                       cached_verb = Verb;
+                               }
+
+                               return cached_verbs;
+                       }
+               }
+
+               FileMatchingInfo[] Paths {
                        get {
-                               return _properties;
+                               if (cached_path != Path) {
+                                       cached_files = SplitPaths ();
+                                       cached_path = Path;
+                               }
+
+                               return cached_files;
+                       }
+               }
+
+               //
+               // Loads the a type by name and verifies that it implements
+               // IHttpHandler or IHttpHandlerFactory
+               //
+               internal static Type LoadType (string type_name)
+               {
+                       Type t = null;
+                       
+                       t = System.Type.GetType (type_name, false);
+                       if (t == null) {
+                               IList tla = System.Web.Compilation.BuildManager.TopLevelAssemblies;
+                               if (tla != null && tla.Count > 0) {
+                                       foreach (Assembly asm in tla) {
+                                               if (asm == null)
+                                                       continue;
+                                               t = asm.GetType (type_name, false);
+                                               if (t != null)
+                                                       break;
+                                       }
+                               }
                        }
+
+                       if (t == null)
+                               throw new HttpException (String.Format ("Failed to load httpHandler type `{0}'", type_name));
+
+                       if (typeof (IHttpHandler).IsAssignableFrom (t) ||
+                           typeof (IHttpHandlerFactory).IsAssignableFrom (t))
+                               return t;
+                       
+                       throw new HttpException (String.Format ("Type {0} does not implement IHttpHandler or IHttpHandlerFactory", type_name));
                }
+
+               internal bool PathMatches (string p)
+               {
+                       int slash = p.LastIndexOf ('/');
+                       string orig = p;
+                       if (slash != -1)
+                               p = p.Substring (slash);
+
+                       for (int j = Paths.Length; j > 0; ){
+                               j--;
+                               FileMatchingInfo fm = Paths [j];
+
+                               if (fm.MatchExact != null)
+                                       return fm.MatchExact.Length == p.Length && StrUtils.EndsWith (p, fm.MatchExact);
+                                       
+                               if (fm.EndsWith != null)
+                                       return StrUtils.EndsWith (p, fm.EndsWith);
+
+                               if (fm.MatchExpr == "*")
+                                       return true;
+
+                               /* convert to regexp */
+                               return fm.RegExp.IsMatch (orig);
+                       }
+                       return false;
+               }
+
+               // Loads the handler, possibly delay-loaded.
+               internal object GetHandlerInstance ()
+               {
+                       IHttpHandler ihh = instance as IHttpHandler;
+                       
+                       if (instance == null || (ihh != null && !ihh.IsReusable)){
+                               if (type == null)
+                                       type = LoadType (Type);
+
+                               instance = Activator.CreateInstance (type);
+                       } 
+                       
+                       return instance;
+               }
+
+               class FileMatchingInfo {
+                       public string MatchExact;
+                       public string MatchExpr;
+
+                       // If set, we can fast-path the patch with string.EndsWith (FMI.EndsWith)
+                       public string EndsWith;
+                       public Regex RegExp;
+               
+                       public FileMatchingInfo (string s)
+                       {
+                               MatchExpr = s;
+
+                               if (s[0] == '*' && (s.IndexOf ('*', 1) == -1))
+                                       EndsWith = s.Substring (1);
+
+                               if (s.IndexOf ('*') == -1)
+                                       MatchExact = "/" + s;
+
+                               if (MatchExpr != "*") {
+                                       string expr = MatchExpr.Replace(".", "\\.").Replace("?", "\\?").Replace("*", ".*");
+                                       if (expr.Length > 0 && expr [0] =='/')
+                                               expr = expr.Substring (1);
+
+                                       expr += "\\z";
+                                       RegExp = new Regex (expr);
+                               }
+                       }
+               }
+#endregion
+
        }
 
 }