/exyus/Uri/UriPatternService.cs

http://exyus.googlecode.com/ · C# · 184 lines · 140 code · 29 blank · 15 comment · 33 complexity · d8151484e18915228415a0fa3ec2e4ff MD5 · raw file

  1. using System;
  2. using System.Collections;
  3. using System.Reflection;
  4. using System.Security.Permissions;
  5. using System.Web;
  6. using System.Web.UI;
  7. using System.Text.RegularExpressions;
  8. namespace Exyus.Web
  9. {
  10. public class UriHandlerFactory : IHttpHandlerFactory
  11. {
  12. private bool _init_complete = false;
  13. private object _ilock = new Object();
  14. private static string _vpath;
  15. private Hashtable _uriPatterns = new Hashtable();
  16. public IHttpHandler GetHandler(HttpContext context, string requestType, string url, string pathTranslated)
  17. {
  18. if (!_init_complete)
  19. Initialize();
  20. // Strip the virtual directory from the front of the url
  21. restart:
  22. string relativeUrl = context.Request.Url.LocalPath.Substring(VPath.Length);
  23. // try to get a match
  24. ConstructorInfo ci = MatchUriPattern(relativeUrl);
  25. // nothing? then check for redir, rewrite, or asp.net
  26. if (ci == null)
  27. {
  28. ExyusRedirect er = new ExyusRedirect();
  29. // check for redirection
  30. string r_url = er.RedirLookUp(relativeUrl);
  31. if (r_url != string.Empty)
  32. {
  33. er.MovedPermanently(r_url);
  34. return null;
  35. }
  36. // check for internal rewrite
  37. r_url = er.RewriteLookUp(relativeUrl);
  38. if (r_url != string.Empty)
  39. {
  40. er.Rewrite(r_url);
  41. goto restart;
  42. }
  43. // try asp.net as a last resort
  44. return PageParser.GetCompiledPageInstance(url, pathTranslated, context);
  45. }
  46. else
  47. {
  48. // get instance
  49. object o = ci.Invoke(new object[] { });
  50. if (o == null)
  51. throw new HttpException(500, "Unable to invoke handler for [" + ci.Name + "]");
  52. // try to pass to factory
  53. IHttpHandlerFactory factory = o as IHttpHandlerFactory;
  54. if (factory != null)
  55. return factory.GetHandler(context, requestType, url, pathTranslated);
  56. // try to pass to handler
  57. IHttpHandler handler = o as IHttpHandler;
  58. if (handler != null)
  59. return handler;
  60. // boom!
  61. throw new HttpException(500, "Error matching uri pattern to handler ");
  62. }
  63. }
  64. public void ReleaseHandler(IHttpHandler handler)
  65. {
  66. IDisposable d = handler as IDisposable;
  67. if (d != null)
  68. d.Dispose();
  69. }
  70. private void Initialize()
  71. {
  72. lock (_ilock)
  73. {
  74. if (_init_complete)
  75. return;
  76. Hashtable cacheUri = new Hashtable();
  77. string[] mtypes = null;
  78. // scan all loaded assemblies
  79. foreach (Assembly assm in AppDomain.CurrentDomain.GetAssemblies())
  80. {
  81. foreach (Type type in assm.GetTypes())
  82. {
  83. try
  84. {
  85. // Look for our attribute on the class
  86. object[] attrs = type.GetCustomAttributes(typeof(UriPattern), false);
  87. if (attrs == null || attrs.Length <= 0)
  88. continue;
  89. // Grab the default constructor
  90. ConstructorInfo ci = type.GetConstructor(Type.EmptyTypes);
  91. if (ci == null)
  92. continue;
  93. // Add a mapping for all the URLs to the given constructor
  94. UriPattern attr = (UriPattern)attrs[0];
  95. foreach (string url in attr.Patterns)
  96. {
  97. _uriPatterns.Add(url.ToLower(), ci);
  98. object[] media = type.GetCustomAttributes(typeof(MediaTypes), false);
  99. if (media != null && media.Length != 0)
  100. {
  101. MediaTypes mt = (MediaTypes)media[0];
  102. mtypes = mt.Types;
  103. }
  104. else
  105. {
  106. HTTPResource rs = (HTTPResource)ci.Invoke(new object[] { });
  107. mtypes = new string[] { rs.ContentType };
  108. rs = null;
  109. }
  110. cacheUri.Add(url.ToLower(), mtypes);
  111. }
  112. }
  113. catch (Exception) { }
  114. }
  115. }
  116. Utility util = new Utility();
  117. util.SaveUriCache(cacheUri);
  118. _init_complete = true;
  119. }
  120. }
  121. private ConstructorInfo MatchUriPattern(string relativeUrl)
  122. {
  123. object rtn = null;
  124. if (_uriPatterns.Count != 0)
  125. {
  126. IDictionaryEnumerator Enumerator = _uriPatterns.GetEnumerator();
  127. while (Enumerator.MoveNext())
  128. {
  129. string pattern = Enumerator.Key.ToString();
  130. //relativeUrl = Regex.Replace(relativeUrl, @"/([^.?]*)(?:\.xcs)?(\?.*)?", "/$1$2", RegexOptions.IgnoreCase);
  131. if (new Regex(pattern, RegexOptions.IgnoreCase).IsMatch(relativeUrl))
  132. {
  133. rtn = Enumerator.Value;
  134. goto exit;
  135. }
  136. }
  137. }
  138. exit:
  139. return rtn as ConstructorInfo;
  140. }
  141. protected string VPath
  142. {
  143. get
  144. {
  145. if (_vpath == null)
  146. {
  147. _vpath = HttpRuntime.AppDomainAppVirtualPath;
  148. if (_vpath[_vpath.Length - 1] == '/')
  149. _vpath = _vpath.TrimEnd('/');
  150. }
  151. return _vpath;
  152. }
  153. }
  154. }
  155. }