2 // System.Web.Configuration.HandlerFactoryConfiguration.cs
6 // Miguel de Icaza (miguel@novell.com
8 // (C) 2002 Ximian, Inc (http://www.ximian.com)
12 // Permission is hereby granted, free of charge, to any person obtaining
13 // a copy of this software and associated documentation files (the
14 // "Software"), to deal in the Software without restriction, including
15 // without limitation the rights to use, copy, modify, merge, publish,
16 // distribute, sublicense, and/or sell copies of the Software, and to
17 // permit persons to whom the Software is furnished to do so, subject to
18 // the following conditions:
20 // The above copyright notice and this permission notice shall be
21 // included in all copies or substantial portions of the Software.
23 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
24 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
25 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
26 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
27 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
28 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
29 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 using System.Collections;
34 using System.Web.Util;
35 using System.Text.RegularExpressions;
37 namespace System.Web.Configuration {
39 class FileMatchingInfo {
40 public string MatchExact;
41 public string MatchExpr;
43 // If set, we can fast-path the patch with string.EndsWith (FMI.EndsWith)
44 public string EndsWith;
46 public FileMatchingInfo (string s)
50 if (s[0] == '*' && (s.IndexOf ('*', 1) == -1))
51 EndsWith = s.Substring (1);
53 if (s.IndexOf ('*') == -1)
59 // If `null', we are the "*" match
60 public string OriginalVerb;
61 public string OriginalPath;
63 public string [] Verbs;
64 public FileMatchingInfo [] files;
66 // To support lazy loading we keep the name around.
67 public string TypeName;
72 public HttpHandler (string verb, string path, string typename, Type t)
78 Verbs = verb.Split (',');
79 string [] paths = path.Split (',');
80 files = new FileMatchingInfo [paths.Length];
83 foreach (string s in paths)
84 files [i++] = new FileMatchingInfo (s);
86 this.TypeName = typename;
91 // Loads the a type by name and verifies that it implements
92 // IHttpHandler or IHttpHandlerFactory
94 public static Type LoadType (string type_name)
99 t = Type.GetType (type_name, true);
100 } catch (Exception e) {
101 throw new HttpException (String.Format ("Failed to load httpHandler type `{0}'", type_name));
104 if (typeof (IHttpHandler).IsAssignableFrom (t) ||
105 typeof (IHttpHandlerFactory).IsAssignableFrom (t))
108 throw new HttpException (String.Format ("Type {0} does not implement IHttpHandler or IHttpHandlerFactory", type_name));
111 public bool PathMatches (string p)
113 for (int j = files.Length; j > 0; ){
115 FileMatchingInfo fm = files [j];
117 if (fm.MatchExact != null)
118 return fm.MatchExact.Length == p.Length && StrUtils.EndsWith (p, fm.MatchExact);
120 if (fm.EndsWith != null)
121 return StrUtils.EndsWith (p, fm.EndsWith);
123 if (fm.MatchExpr == "*")
126 /* convert to regexp */
127 string match_regexp = fm.MatchExpr.Replace(".", "\\.").Replace("?", "\\?").Replace("*", ".*");
128 return Regex.IsMatch (p, match_regexp);
133 // Loads the handler, possibly delay-loaded.
134 public object GetHandlerInstance ()
136 IHttpHandler ihh = instance as IHttpHandler;
138 if (instance == null || (ihh != null && !ihh.IsReusable)){
140 type = LoadType (TypeName);
142 instance = Activator.CreateInstance (type);
149 class HandlerFactoryConfiguration {
151 HandlerFactoryConfiguration parent;
152 public HandlerFactoryConfiguration (HandlerFactoryConfiguration parent)
154 this.parent = parent;
156 handlers = new ArrayList ();
164 public void Add (string verb, string path, string type_name, bool validate)
169 type = HttpHandler.LoadType (type_name);
171 throw new HttpException (String.Format ("Can not load {0}", type_name));
175 handlers.Add (new HttpHandler (verb, path, type_name, type));
178 public HttpHandler Remove (string verb, string path)
180 int top = handlers.Count;
182 for (int i = 0; i < top; i++){
183 HttpHandler handler = (HttpHandler) handlers [i];
185 if (verb == handler.OriginalVerb && path == handler.OriginalPath){
193 public object LocateHandler (string verb, string filepath)
195 int top = handlers.Count;
197 for (int i = 0; i < top; i++){
198 HttpHandler handler = (HttpHandler) handlers [i];
200 if (handler.Verbs == null){
201 if (handler.PathMatches (filepath))
202 return handler.GetHandlerInstance ();
206 string [] verbs = handler.Verbs;
207 for (int j = verbs.Length; j > 0; ){
209 if (verbs [j] != verb)
211 if (handler.PathMatches (filepath))
212 return handler.GetHandlerInstance ();
217 return parent.LocateHandler (verb, filepath);