2 // System.Web.Configuration.HandlerFactoryConfiguration.cs
6 // Miguel de Icaza (miguel@novell.com)
7 // Gonzalo Paniagua Javier (gonzalo@novell.com)
9 // (C) 2005 Novell, Inc (http://www.novell.com)
13 // Permission is hereby granted, free of charge, to any person obtaining
14 // a copy of this software and associated documentation files (the
15 // "Software"), to deal in the Software without restriction, including
16 // without limitation the rights to use, copy, modify, merge, publish,
17 // distribute, sublicense, and/or sell copies of the Software, and to
18 // permit persons to whom the Software is furnished to do so, subject to
19 // the following conditions:
21 // The above copyright notice and this permission notice shall be
22 // included in all copies or substantial portions of the Software.
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
25 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
26 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
27 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
28 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
29 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
30 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
34 using System.Collections;
35 using System.Web.Util;
36 using System.Text.RegularExpressions;
38 namespace System.Web.Configuration {
40 // If `null', we are the "*" match
41 public string OriginalVerb;
42 public string OriginalPath;
44 public string [] Verbs;
45 public FileMatchingInfo [] files;
47 // To support lazy loading we keep the name around.
48 public string TypeName;
53 public HttpHandler (string verb, string path, string typename, Type t)
59 Verbs = verb.Split (',');
61 this.TypeName = typename;
66 // Loads the a type by name and verifies that it implements
67 // IHttpHandler or IHttpHandlerFactory
69 public static Type LoadType (string type_name)
74 t = HttpApplication.LoadType (type_name, true);
76 throw new HttpException (String.Format ("Failed to load httpHandler type `{0}'", type_name));
79 if (typeof (IHttpHandler).IsAssignableFrom (t) ||
80 typeof (IHttpHandlerFactory).IsAssignableFrom (t))
83 throw new HttpException (String.Format ("Type {0} does not implement IHttpHandler or IHttpHandlerFactory", type_name));
86 public bool PathMatches (string p)
88 string [] paths = OriginalPath.Split (',');
89 files = new FileMatchingInfo [paths.Length];
92 foreach (string s in paths)
93 files [i++] = new FileMatchingInfo (s);
95 int slash = p.LastIndexOf ('/');
98 p = p.Substring (slash);
100 for (int j = files.Length; j > 0; ){
102 FileMatchingInfo fm = files [j];
104 if (fm.MatchExact != null)
105 return fm.MatchExact.Length == orig.Length && StrUtils.EndsWith (orig, fm.MatchExact, true);
107 if (fm.EndsWith != null)
108 return StrUtils.EndsWith (p, fm.EndsWith, true);
110 if (fm.MatchExpr == "*")
113 /* convert to regexp */
114 return fm.RegExp.IsMatch (orig);
119 // Loads the handler, possibly delay-loaded.
120 public object GetHandlerInstance ()
122 IHttpHandler ihh = instance as IHttpHandler;
124 if (instance == null || (ihh != null && !ihh.IsReusable)){
126 type = LoadType (TypeName);
128 instance = Activator.CreateInstance (type);
135 class HandlerFactoryConfiguration {
137 //HandlerFactoryConfiguration parent;
140 public HandlerFactoryConfiguration (HandlerFactoryConfiguration parent)
142 //this.parent = parent;
144 if (parent != null) {
145 handlers = new ArrayList (parent.handlers);
146 parent_items = handlers.Count;
148 handlers = new ArrayList ();
154 HttpApplication.ClearHandlerCache ();
158 public void Add (string verb, string path, string type_name, bool validate)
163 type = HttpHandler.LoadType (type_name);
165 throw new HttpException (String.Format ("Can not load {0}", type_name));
169 HttpApplication.ClearHandlerCache ();
170 handlers.Add (new HttpHandler (verb, path, type_name, type));
173 public bool Remove (string verb, string path)
175 for (int i = handlers.Count - 1; i >= 0; i--) {
176 HttpHandler handler = (HttpHandler) handlers [i];
178 if (verb == handler.OriginalVerb && path == handler.OriginalPath){
179 HttpApplication.ClearHandlerCache ();
180 handlers.RemoveAt (i);
188 public object LocateHandler (string verb, string filepath)
191 int count = handlers.Count;
192 for (int k = 0; k < 2; k++) {
193 // First iteration searches for the mapping in the items added to this
194 // instance. The second one searches through the parent items if any.
195 start = (k == 0) ? parent_items : 0;
196 end = (k == 0) ? count : parent_items;
197 for (int i = start; i < end; 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 ();