HandlerFactoryConfiguration.cs 5.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236
  1. //
  2. // System.Web.Configuration.HandlerFactoryConfiguration.cs
  3. //
  4. //
  5. // Authors:
  6. // Miguel de Icaza ([email protected]
  7. //
  8. // (C) 2002 Ximian, Inc (http://www.ximian.com)
  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. using System;
  31. using System.Collections;
  32. using System.Web.Util;
  33. using System.Text.RegularExpressions;
  34. namespace System.Web.Configuration {
  35. class FileMatchingInfo {
  36. public string MatchExact;
  37. public string MatchExpr;
  38. // If set, we can fast-path the patch with string.EndsWith (FMI.EndsWith)
  39. public string EndsWith;
  40. public Regex RegExp;
  41. public FileMatchingInfo (string s)
  42. {
  43. MatchExpr = s;
  44. if (s[0] == '*' && (s.IndexOf ('*', 1) == -1))
  45. EndsWith = s.Substring (1);
  46. if (s.IndexOf ('*') == -1)
  47. MatchExact = "/" + s;
  48. if (MatchExpr != "*") {
  49. string expr = MatchExpr.Replace(".", "\\.").Replace("?", "\\?").Replace("*", ".*");
  50. if (expr.Length > 0 && expr [0] =='/')
  51. expr = expr.Substring (1);
  52. expr += "\\z";
  53. RegExp = new Regex (expr);
  54. }
  55. }
  56. }
  57. class HttpHandler {
  58. // If `null', we are the "*" match
  59. public string OriginalVerb;
  60. public string OriginalPath;
  61. public string [] Verbs;
  62. public FileMatchingInfo [] files;
  63. // To support lazy loading we keep the name around.
  64. public string TypeName;
  65. Type type;
  66. object instance;
  67. public HttpHandler (string verb, string path, string typename, Type t)
  68. {
  69. OriginalVerb = verb;
  70. OriginalPath = path;
  71. if (verb != "*")
  72. Verbs = verb.Split (',');
  73. string [] paths = path.Split (',');
  74. files = new FileMatchingInfo [paths.Length];
  75. int i = 0;
  76. foreach (string s in paths)
  77. files [i++] = new FileMatchingInfo (s);
  78. this.TypeName = typename;
  79. type = t;
  80. }
  81. //
  82. // Loads the a type by name and verifies that it implements
  83. // IHttpHandler or IHttpHandlerFactory
  84. //
  85. public static Type LoadType (string type_name)
  86. {
  87. Type t;
  88. try {
  89. t = Type.GetType (type_name, true);
  90. } catch (Exception e) {
  91. throw new HttpException (String.Format ("Failed to load httpHandler type `{0}'", type_name));
  92. }
  93. if (typeof (IHttpHandler).IsAssignableFrom (t) ||
  94. typeof (IHttpHandlerFactory).IsAssignableFrom (t))
  95. return t;
  96. throw new HttpException (String.Format ("Type {0} does not implement IHttpHandler or IHttpHandlerFactory", type_name));
  97. }
  98. public bool PathMatches (string p)
  99. {
  100. int slash = p.LastIndexOf ('/');
  101. string orig = p;
  102. if (slash != -1)
  103. p = p.Substring (slash);
  104. for (int j = files.Length; j > 0; ){
  105. j--;
  106. FileMatchingInfo fm = files [j];
  107. if (fm.MatchExact != null)
  108. return fm.MatchExact.Length == p.Length && StrUtils.EndsWith (p, fm.MatchExact);
  109. if (fm.EndsWith != null)
  110. return StrUtils.EndsWith (p, fm.EndsWith);
  111. if (fm.MatchExpr == "*")
  112. return true;
  113. /* convert to regexp */
  114. return fm.RegExp.IsMatch (orig);
  115. }
  116. return false;
  117. }
  118. // Loads the handler, possibly delay-loaded.
  119. public object GetHandlerInstance ()
  120. {
  121. IHttpHandler ihh = instance as IHttpHandler;
  122. if (instance == null || (ihh != null && !ihh.IsReusable)){
  123. if (type == null)
  124. type = LoadType (TypeName);
  125. instance = Activator.CreateInstance (type);
  126. }
  127. return instance;
  128. }
  129. }
  130. class HandlerFactoryConfiguration {
  131. ArrayList handlers;
  132. HandlerFactoryConfiguration parent;
  133. public HandlerFactoryConfiguration (HandlerFactoryConfiguration parent)
  134. {
  135. this.parent = parent;
  136. handlers = new ArrayList ();
  137. }
  138. public void Clear ()
  139. {
  140. handlers.Clear ();
  141. }
  142. public void Add (string verb, string path, string type_name, bool validate)
  143. {
  144. Type type;
  145. if (validate){
  146. type = HttpHandler.LoadType (type_name);
  147. if (type == null)
  148. throw new HttpException (String.Format ("Can not load {0}", type_name));
  149. } else
  150. type = null;
  151. handlers.Add (new HttpHandler (verb, path, type_name, type));
  152. }
  153. public HttpHandler Remove (string verb, string path)
  154. {
  155. int top = handlers.Count;
  156. for (int i = 0; i < top; i++){
  157. HttpHandler handler = (HttpHandler) handlers [i];
  158. if (verb == handler.OriginalVerb && path == handler.OriginalPath){
  159. handlers.Remove (i);
  160. return handler;
  161. }
  162. }
  163. return null;
  164. }
  165. public object LocateHandler (string verb, string filepath)
  166. {
  167. int top = handlers.Count;
  168. for (int i = 0; i < top; i++){
  169. HttpHandler handler = (HttpHandler) handlers [i];
  170. if (handler.Verbs == null){
  171. if (handler.PathMatches (filepath))
  172. return handler.GetHandlerInstance ();
  173. continue;
  174. }
  175. string [] verbs = handler.Verbs;
  176. for (int j = verbs.Length; j > 0; ){
  177. j--;
  178. if (verbs [j] != verb)
  179. continue;
  180. if (handler.PathMatches (filepath))
  181. return handler.GetHandlerInstance ();
  182. }
  183. }
  184. if (parent != null)
  185. return parent.LocateHandler (verb, filepath);
  186. else
  187. return null;
  188. }
  189. }
  190. }