| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247 |
- //
- // System.Web.Configuration.HandlerFactoryConfiguration.cs
- //
- //
- // Authors:
- // Miguel de Icaza ([email protected])
- // Gonzalo Paniagua Javier ([email protected])
- //
- // (C) 2005 Novell, Inc (http://www.novell.com)
- //
- //
- // Permission is hereby granted, free of charge, to any person obtaining
- // a copy of this software and associated documentation files (the
- // "Software"), to deal in the Software without restriction, including
- // without limitation the rights to use, copy, modify, merge, publish,
- // distribute, sublicense, and/or sell copies of the Software, and to
- // permit persons to whom the Software is furnished to do so, subject to
- // the following conditions:
- //
- // The above copyright notice and this permission notice shall be
- // included in all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
- // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
- // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
- // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
- // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
- // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- //
- using System;
- using System.Collections;
- using System.Web.Util;
- using System.Text.RegularExpressions;
- namespace System.Web.Configuration {
- 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);
- }
- }
- }
-
- class HttpHandler {
- // If `null', we are the "*" match
- public string OriginalVerb;
- public string OriginalPath;
-
- public string [] Verbs;
- public FileMatchingInfo [] files;
- // To support lazy loading we keep the name around.
- public string TypeName;
- Type type;
- object instance;
-
- public HttpHandler (string verb, string path, string typename, Type t)
- {
- OriginalVerb = verb;
- OriginalPath = path;
-
- if (verb != "*")
- Verbs = verb.Split (',');
- string [] paths = path.Split (',');
- files = new FileMatchingInfo [paths.Length];
- int i = 0;
- foreach (string s in paths)
- files [i++] = new FileMatchingInfo (s);
-
- this.TypeName = typename;
- type = t;
- }
- //
- // Loads the a type by name and verifies that it implements
- // IHttpHandler or IHttpHandlerFactory
- //
- public static Type LoadType (string type_name)
- {
- Type t;
-
- try {
- t = Type.GetType (type_name, true);
- } catch (Exception e) {
- 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));
- }
- public bool PathMatches (string p)
- {
- int slash = p.LastIndexOf ('/');
- string orig = p;
- if (slash != -1)
- p = p.Substring (slash);
- for (int j = files.Length; j > 0; ){
- j--;
- FileMatchingInfo fm = files [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.
- public object GetHandlerInstance ()
- {
- IHttpHandler ihh = instance as IHttpHandler;
-
- if (instance == null || (ihh != null && !ihh.IsReusable)){
- if (type == null)
- type = LoadType (TypeName);
- instance = Activator.CreateInstance (type);
- }
-
- return instance;
- }
- }
-
- class HandlerFactoryConfiguration {
- ArrayList handlers;
- HandlerFactoryConfiguration parent;
- int parent_items;
- public HandlerFactoryConfiguration (HandlerFactoryConfiguration parent)
- {
- this.parent = parent;
- if (parent != null) {
- handlers = new ArrayList (parent.handlers);
- parent_items = handlers.Count;
- } else {
- handlers = new ArrayList ();
- }
- }
- public void Clear ()
- {
- handlers.Clear ();
- }
- public void Add (string verb, string path, string type_name, bool validate)
- {
- Type type;
- if (validate){
- type = HttpHandler.LoadType (type_name);
- if (type == null)
- throw new HttpException (String.Format ("Can not load {0}", type_name));
- } else
- type = null;
-
- handlers.Add (new HttpHandler (verb, path, type_name, type));
- }
- public bool Remove (string verb, string path)
- {
- for (int i = handlers.Count - 1; i >= 0; i--) {
- HttpHandler handler = (HttpHandler) handlers [i];
- if (verb == handler.OriginalVerb && path == handler.OriginalPath){
- handlers.RemoveAt (i);
- return true;
- }
- }
- return false;
- }
- public object LocateHandler (string verb, string filepath)
- {
- int start, end;
- int count = handlers.Count;
- for (int k = 0; k < 2; k++) {
- // First iteration searches for the mapping in the items added to this
- // instance. The second one searches through the parent items if any.
- start = (k == 0) ? parent_items : 0;
- end = (k == 0) ? count : parent_items;
- for (int i = start; i < end; i++) {
- HttpHandler handler = (HttpHandler) handlers [i];
- if (handler.Verbs == null){
- if (handler.PathMatches (filepath))
- return handler.GetHandlerInstance ();
- continue;
- }
- string [] verbs = handler.Verbs;
- for (int j = verbs.Length; j > 0; ){
- j--;
- if (verbs [j] != verb)
- continue;
- if (handler.PathMatches (filepath))
- return handler.GetHandlerInstance ();
- }
- }
- }
- return null;
- }
- }
- }
|