Fixing an issue with output parameters that are of type IntPtr
[castle.git] / MonoRail / Castle.MonoRail.Framework / Services / DefaultUrlTokenizer.cs
blobba16439ee5c5fb7f5bd5caea57fd44f310d4ee17
1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
15 namespace Castle.MonoRail.Framework.Services
17 using System;
18 using System.Collections;
19 using System.Collections.Specialized;
20 using System.IO;
21 using System.Text;
22 using Configuration;
23 using Core;
25 /// <summary>
26 /// Breaks the url into smaller pieces to find out
27 /// the requested controller, action and optionally the area.
28 /// <para>
29 /// It alsos checks for default urls which map a single resource to an area/controller/action
30 /// </para>
31 /// </summary>
32 public class DefaultUrlTokenizer : IUrlTokenizer, IServiceEnabledComponent
34 private readonly IDictionary defaultUrl2CustomUrlInfo = new HybridDictionary(true);
36 /// <summary>
37 /// Adds the default rule mapping.
38 /// </summary>
39 /// <remarks>
40 /// A defautl rule can associate something like a 'default.castle'
41 /// to a controller/action like 'Home/index.castle'
42 /// </remarks>
43 /// <param name="url">The URL.</param>
44 /// <param name="area">The area.</param>
45 /// <param name="controller">The controller.</param>
46 /// <param name="action">The action.</param>
47 public void AddDefaultRule(string url, string area, string controller, string action)
49 if (area == null)
51 area = string.Empty;
54 defaultUrl2CustomUrlInfo[url] = new UrlInfo(area, controller, action);
57 #region IServiceEnabledComponent
59 /// <summary>
60 /// Services the specified provider.
61 /// </summary>
62 /// <param name="provider">The provider.</param>
63 public void Service(IServiceProvider provider)
65 IMonoRailConfiguration config = (IMonoRailConfiguration) provider.GetService(typeof(IMonoRailConfiguration));
67 foreach(DefaultUrl url in config.DefaultUrls)
69 AddDefaultRule(url.Url, url.Area, url.Controller, url.Action);
73 #endregion
75 #region IUrlTokenizer
77 /// <summary>
78 /// Tokenizes the URL.
79 /// </summary>
80 /// <param name="rawUrl">The raw URL.</param>
81 /// <param name="pathInfo">The path info.</param>
82 /// <param name="uri">The URI.</param>
83 /// <param name="isLocal">if set to <c>true</c> request is local.</param>
84 /// <param name="appVirtualDir">Virtual directory</param>
85 /// <returns></returns>
86 public UrlInfo TokenizeUrl(string rawUrl, string pathInfo, Uri uri, bool isLocal, string appVirtualDir)
88 if (rawUrl == null || rawUrl.Length == 0)
90 throw new ArgumentNullException("rawUrl", "rawUrl cannot be null or empty");
93 string domain = uri.Host;
94 string subdomain = GetDomainToken(domain, 0);
96 // if (subdomain != null && subdomain.Length < domain.Length)
97 // {
98 // // Strip the subdomain from the main domain name
99 // domain = domain.Substring(subdomain.Length);
100 // }
102 if (rawUrl[0] == '/')
104 rawUrl = rawUrl.Substring(1);
107 // Strip the appVirtualDir from the Url
108 if (appVirtualDir != null && appVirtualDir != "")
110 appVirtualDir = appVirtualDir.ToLower(System.Globalization.CultureInfo.InvariantCulture).Substring(1);
112 if (!rawUrl.StartsWith(appVirtualDir, true, System.Globalization.CultureInfo.InvariantCulture))
114 // Sanity check
115 throw new UrlTokenizerException("Url does not start with the virtual dir");
118 rawUrl = rawUrl.Substring(appVirtualDir.Length);
121 string area, controller, action;
123 // Is the url a custom url?
124 UrlInfo custom = (UrlInfo) defaultUrl2CustomUrlInfo[rawUrl];
126 if (custom != null)
128 area = custom.Area;
129 controller = custom.Controller;
130 action = custom.Action;
132 else
134 ExtractAreaControllerAction(rawUrl, out area, out controller, out action);
137 string extension = GetExtension(rawUrl);
139 return new UrlInfo(domain, subdomain, appVirtualDir, uri.Scheme, uri.Port, rawUrl, area, controller, action, extension, pathInfo);
142 #endregion
144 /// <summary>
145 /// Extracts the area controller action.
146 /// </summary>
147 /// <param name="rawUrl">The raw URL.</param>
148 /// <param name="area">The area.</param>
149 /// <param name="controller">The controller.</param>
150 /// <param name="action">The action.</param>
151 private void ExtractAreaControllerAction(string rawUrl, out string area, out string controller, out string action)
153 string[] parts = rawUrl.Split('/');
155 if (parts.Length < 2)
157 throw new UrlTokenizerException("Url smaller than 2 tokens");
160 action = parts[parts.Length - 1];
162 int fileNameIndex = action.IndexOf('.');
164 if (fileNameIndex != -1)
166 action = action.Substring(0, fileNameIndex);
169 controller = parts[parts.Length - 2];
171 area = string.Empty;
173 if (parts.Length - 3 == 0)
175 area = parts[parts.Length - 3];
177 else if (parts.Length - 3 > 0)
179 StringBuilder areaSB = new StringBuilder();
181 for(int i = 0; i <= parts.Length - 3; i++)
183 if (parts[i] != null && parts[i].Length > 0)
185 areaSB.Append(parts[i]).Append('/');
189 if (areaSB.Length > 0)
191 areaSB.Length -= 1;
194 area = areaSB.ToString();
198 /// <summary>
199 /// Gets the domain token.
200 /// </summary>
201 /// <param name="domain">The domain.</param>
202 /// <param name="token">The token index.</param>
203 /// <returns></returns>
204 protected static string GetDomainToken(string domain, int token)
206 string[] parts = domain.Split('.');
208 if (parts.Length == 1)
210 return null;
213 if (token < parts.Length)
215 return parts[token];
218 return string.Empty;
221 /// <summary>
222 /// Gets the extension of the requested urls page without the preceding period.
223 /// </summary>
224 /// <param name="url">URL.</param>
225 /// <returns>The resource file extension on the url (without the period).</returns>
226 protected static string GetExtension(string url)
228 string ext = Path.GetExtension(url);
230 if (ext.Length > 1)
232 return ext.Substring(1);
235 return ext;