Fix the build.
[castle.git] / MonoRail / Castle.MonoRail.Framework / Services / DefaultUrlTokenizer.cs
bloba64f6de24fe877cc07c4964f398ce5867262907b
1 // Copyright 2004-2007 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 Castle.Core;
23 using Castle.MonoRail.Framework.Configuration;
24 using Castle.MonoRail.Framework.Internal;
26 /// <summary>
27 /// Breaks the url into smaller pieces to find out
28 /// the requested controller, action and optionally the area.
29 /// <para>
30 /// It alsos checks for default urls which map a single resource to an area/controller/action
31 /// </para>
32 /// </summary>
33 public class DefaultUrlTokenizer : IUrlTokenizer, IServiceEnabledComponent
35 private readonly IDictionary defaultUrl2CustomUrlInfo = new HybridDictionary(true);
37 /// <summary>
38 /// Adds the default rule mapping.
39 /// </summary>
40 /// <remarks>
41 /// A defautl rule can associate something like a 'default.castle'
42 /// to a controller/action like 'Home/index.castle'
43 /// </remarks>
44 /// <param name="url">The URL.</param>
45 /// <param name="area">The area.</param>
46 /// <param name="controller">The controller.</param>
47 /// <param name="action">The action.</param>
48 public void AddDefaultRule(string url, string area, string controller, string action)
50 if (area == null)
52 area = string.Empty;
55 defaultUrl2CustomUrlInfo[url] = new UrlInfo(area, controller, action);
58 #region IServiceEnabledComponent
60 /// <summary>
61 /// Services the specified provider.
62 /// </summary>
63 /// <param name="provider">The provider.</param>
64 public void Service(IServiceProvider provider)
66 MonoRailConfiguration config = (MonoRailConfiguration) provider.GetService(typeof(MonoRailConfiguration));
68 foreach(DefaultUrl url in config.DefaultUrls)
70 AddDefaultRule(url.Url, url.Area, url.Controller, url.Action);
74 #endregion
76 #region IUrlTokenizer
78 /// <summary>
79 /// Tokenizes the URL.
80 /// </summary>
81 /// <param name="rawUrl">The raw URL.</param>
82 /// <param name="pathInfo">The path info.</param>
83 /// <param name="uri">The URI.</param>
84 /// <param name="isLocal">if set to <c>true</c> request is local.</param>
85 /// <param name="appVirtualDir">Virtual directory</param>
86 /// <returns></returns>
87 public UrlInfo TokenizeUrl(string rawUrl, string pathInfo, Uri uri, bool isLocal, string appVirtualDir)
89 if (rawUrl == null || rawUrl.Length == 0)
91 throw new ArgumentNullException("rawUrl", "rawUrl cannot be null or empty");
94 string domain = uri.Host;
95 string subdomain = GetDomainToken(domain, 0);
97 if (subdomain.Length < subdomain.Length)
99 // Strip the subdomain from the main domain name
100 domain = domain.Substring(subdomain.Length);
103 if (rawUrl[0] == '/')
105 rawUrl = rawUrl.Substring(1);
108 // Strip the appVirtualDir from the Url
109 if (appVirtualDir != null && appVirtualDir != "")
111 appVirtualDir = appVirtualDir.ToLower(System.Globalization.CultureInfo.InvariantCulture).Substring(1);
113 if (!rawUrl.StartsWith(appVirtualDir, true, System.Globalization.CultureInfo.InvariantCulture))
115 // Sanity check
116 throw new UrlTokenizerException("Url does not start with the virtual dir");
119 rawUrl = rawUrl.Substring(appVirtualDir.Length);
122 string area, controller, action;
124 // Is the url a custom url?
125 UrlInfo custom = (UrlInfo) defaultUrl2CustomUrlInfo[rawUrl];
127 if (custom != null)
129 area = custom.Area;
130 controller = custom.Controller;
131 action = custom.Action;
133 else
135 ExtractAreaControllerAction(rawUrl, out area, out controller, out action);
138 string extension = GetExtension(rawUrl);
140 return new UrlInfo(domain, subdomain, appVirtualDir, uri.Scheme, uri.Port, rawUrl, area, controller, action, extension, pathInfo);
143 #endregion
145 /// <summary>
146 /// Extracts the area controller action.
147 /// </summary>
148 /// <param name="rawUrl">The raw URL.</param>
149 /// <param name="area">The area.</param>
150 /// <param name="controller">The controller.</param>
151 /// <param name="action">The action.</param>
152 private void ExtractAreaControllerAction(string rawUrl, out string area, out string controller, out string action)
154 string[] parts = rawUrl.Split('/');
156 if (parts.Length < 2)
158 throw new UrlTokenizerException("Url smaller than 2 tokens");
161 action = parts[parts.Length - 1];
163 int fileNameIndex = action.IndexOf('.');
165 if (fileNameIndex != -1)
167 action = action.Substring(0, fileNameIndex);
170 controller = parts[parts.Length - 2];
172 area = string.Empty;
174 if (parts.Length - 3 == 0)
176 area = parts[parts.Length - 3];
178 else if (parts.Length - 3 > 0)
180 StringBuilder areaSB = new StringBuilder();
182 for(int i = 0; i <= parts.Length - 3; i++)
184 if (parts[i] != null && parts[i].Length > 0)
186 areaSB.Append(parts[i]).Append('/');
190 if (areaSB.Length > 0)
192 areaSB.Length -= 1;
195 area = areaSB.ToString();
199 /// <summary>
200 /// Gets the domain token.
201 /// </summary>
202 /// <param name="domain">The domain.</param>
203 /// <param name="token">The token index.</param>
204 /// <returns></returns>
205 protected static string GetDomainToken(string domain, int token)
207 string[] parts = domain.Split('.');
209 if (token < parts.Length)
211 return parts[token];
214 return string.Empty;
217 /// <summary>
218 /// Gets the extension of the requested urls page without the preceding period.
219 /// </summary>
220 /// <param name="url">URL.</param>
221 /// <returns>The resource file extension on the url (without the period).</returns>
222 protected static string GetExtension(string url)
224 string ext = Path.GetExtension(url);
226 if (ext.Length > 1)
228 return ext.Substring(1);
231 return ext;