In .:
[mono.git] / mcs / class / System.Web / System.Web.Configuration_2.0 / HttpHandlerAction.cs
1 //
2 // System.Web.Configuration.HttpHandlerAction
3 //
4 // Authors:
5 //      Chris Toshok (toshok@ximian.com)
6 //
7 // (C) 2005 Novell, Inc (http://www.novell.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
31 #if NET_2_0
32
33 using System;
34 using System.ComponentModel;
35 using System.Configuration;
36 using System.Text.RegularExpressions;
37 using System.Web.Util;
38
39 namespace System.Web.Configuration
40 {
41         public sealed class HttpHandlerAction: ConfigurationElement
42         {
43                 static ConfigurationPropertyCollection _properties;
44                 static ConfigurationProperty pathProp;
45                 static ConfigurationProperty typeProp;
46                 static ConfigurationProperty validateProp;
47                 static ConfigurationProperty verbProp;
48
49                 static HttpHandlerAction ()
50                 {
51                         pathProp = new ConfigurationProperty ("path", typeof (string), null,
52                                                               TypeDescriptor.GetConverter (typeof (string)),
53                                                               PropertyHelper.NonEmptyStringValidator,
54                                                               ConfigurationPropertyOptions.IsRequired | ConfigurationPropertyOptions.IsKey);
55                         typeProp = new ConfigurationProperty ("type", typeof (string), null,
56                                                               TypeDescriptor.GetConverter (typeof (string)),
57                                                               PropertyHelper.NonEmptyStringValidator,
58                                                               ConfigurationPropertyOptions.IsRequired);
59                         validateProp = new ConfigurationProperty ("validate", typeof (bool), true);
60                         verbProp = new ConfigurationProperty ("verb", typeof (string), null,
61                                                               TypeDescriptor.GetConverter (typeof (string)),
62                                                               PropertyHelper.NonEmptyStringValidator,
63                                                               ConfigurationPropertyOptions.IsRequired);
64
65                         _properties = new ConfigurationPropertyCollection ();
66                         _properties.Add (pathProp);
67                         _properties.Add (typeProp);
68                         _properties.Add (validateProp);
69                         _properties.Add (verbProp);
70                 }
71
72                 internal HttpHandlerAction ()
73                 { }
74
75                 public HttpHandlerAction (string path, string type, string verb)
76                         : this (path, type, verb, true)
77                 { }
78
79                 public HttpHandlerAction (string path, string type, string verb, bool validate)
80                 {
81                         Path = path;
82                         Type = type;
83                         Verb = verb;
84                         Validate = validate;
85                 }
86
87                 [ConfigurationProperty ("path", Options = ConfigurationPropertyOptions.IsRequired | ConfigurationPropertyOptions.IsKey)]
88                 // LAMESPEC: MS lists no validator here but provides one in Properties.
89                 public string Path {
90                         get { return (string) base[pathProp]; }
91                         set { base[pathProp] = value; }
92                 }
93
94                 [ConfigurationProperty ("type", Options = ConfigurationPropertyOptions.IsRequired)]
95                 // LAMESPEC: MS lists no validator here but provides one in Properties.
96                 public string Type {
97                         get { return (string) base[typeProp]; }
98                         set { base[typeProp] = value; }
99                 }
100
101                 [ConfigurationProperty ("validate", DefaultValue = true)]
102                 public bool Validate {
103                         get { return (bool) base[validateProp]; }
104                         set { base[validateProp] = value; }
105                 }
106
107                 [ConfigurationProperty ("verb", Options = ConfigurationPropertyOptions.IsRequired | ConfigurationPropertyOptions.IsKey)]
108                 // LAMESPEC: MS lists no validator here but provides one in Properties.
109                 public string Verb {
110                         get { return (string) base[verbProp]; }
111                         set { base[verbProp] = value; }
112                 }
113
114                 protected override ConfigurationPropertyCollection Properties {
115                         get { return _properties; }
116                 }
117
118 #region CompatabilityCode
119                 object instance;
120                 Type type;
121
122                 string cached_verb = null;
123                 string[] cached_verbs;
124
125                 string cached_path = null;
126                 FileMatchingInfo[] cached_files;
127
128                 FileMatchingInfo[] SplitPaths ()
129                 {
130                         string [] paths = Path.Split (',');
131                         cached_files = new FileMatchingInfo [paths.Length];
132
133                         int i = 0;
134                         foreach (string s in paths)
135                                 cached_files [i++] = new FileMatchingInfo (s);
136
137                         return cached_files;
138                 }
139
140                 string[] SplitVerbs ()
141                 {
142                         if (Verb == "*")
143                                 cached_verbs = null;
144                         else
145                                 cached_verbs = Verb.Split (',');
146
147                         return cached_verbs;
148                 }
149
150                 internal string[] Verbs {
151                         get {
152                                 if (cached_verb != Verb) {
153                                         cached_verbs = SplitVerbs();
154                                         cached_verb = Verb;
155                                 }
156
157                                 return cached_verbs;
158                         }
159                 }
160
161                 FileMatchingInfo[] Paths {
162                         get {
163                                 if (cached_path != Path) {
164                                         cached_files = SplitPaths ();
165                                         cached_path = Path;
166                                 }
167
168                                 return cached_files;
169                         }
170                 }
171
172                 //
173                 // Loads the a type by name and verifies that it implements
174                 // IHttpHandler or IHttpHandlerFactory
175                 //
176                 internal static Type LoadType (string type_name)
177                 {
178                         Type t;
179                         
180                         try {
181                                 t = System.Type.GetType (type_name, true);
182                         } catch (Exception e) {
183                                 throw new HttpException (String.Format ("Failed to load httpHandler type `{0}'", type_name));
184                         }
185
186                         if (typeof (IHttpHandler).IsAssignableFrom (t) ||
187                             typeof (IHttpHandlerFactory).IsAssignableFrom (t))
188                                 return t;
189                         
190                         throw new HttpException (String.Format ("Type {0} does not implement IHttpHandler or IHttpHandlerFactory", type_name));
191                 }
192
193                 internal bool PathMatches (string p)
194                 {
195                         int slash = p.LastIndexOf ('/');
196                         string orig = p;
197                         if (slash != -1)
198                                 p = p.Substring (slash);
199
200                         for (int j = Paths.Length; j > 0; ){
201                                 j--;
202                                 FileMatchingInfo fm = Paths [j];
203
204                                 if (fm.MatchExact != null)
205                                         return fm.MatchExact.Length == p.Length && StrUtils.EndsWith (p, fm.MatchExact);
206                                         
207                                 if (fm.EndsWith != null)
208                                         return StrUtils.EndsWith (p, fm.EndsWith);
209
210                                 if (fm.MatchExpr == "*")
211                                         return true;
212
213                                 /* convert to regexp */
214                                 return fm.RegExp.IsMatch (orig);
215                         }
216                         return false;
217                 }
218
219                 // Loads the handler, possibly delay-loaded.
220                 internal object GetHandlerInstance ()
221                 {
222                         IHttpHandler ihh = instance as IHttpHandler;
223                         
224                         if (instance == null || (ihh != null && !ihh.IsReusable)){
225                                 if (type == null)
226                                         type = LoadType (Type);
227
228                                 instance = Activator.CreateInstance (type);
229                         } 
230                         
231                         return instance;
232                 }
233
234                 class FileMatchingInfo {
235                         public string MatchExact;
236                         public string MatchExpr;
237
238                         // If set, we can fast-path the patch with string.EndsWith (FMI.EndsWith)
239                         public string EndsWith;
240                         public Regex RegExp;
241                 
242                         public FileMatchingInfo (string s)
243                         {
244                                 MatchExpr = s;
245
246                                 if (s[0] == '*' && (s.IndexOf ('*', 1) == -1))
247                                         EndsWith = s.Substring (1);
248
249                                 if (s.IndexOf ('*') == -1)
250                                         MatchExact = "/" + s;
251
252                                 if (MatchExpr != "*") {
253                                         string expr = MatchExpr.Replace(".", "\\.").Replace("?", "\\?").Replace("*", ".*");
254                                         if (expr.Length > 0 && expr [0] =='/')
255                                                 expr = expr.Substring (1);
256
257                                         expr += "\\z";
258                                         RegExp = new Regex (expr);
259                                 }
260                         }
261                 }
262 #endregion
263
264         }
265
266 }
267
268 #endif