1 // Copyright 2004-2008 Castle Project - http://www.castleproject.org/
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
7 // http://www.apache.org/licenses/LICENSE-2.0
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
18 using System
.Collections
;
19 using System
.Collections
.Specialized
;
26 /// Breaks the url into smaller pieces to find out
27 /// the requested controller, action and optionally the area.
29 /// It alsos checks for default urls which map a single resource to an area/controller/action
32 public class DefaultUrlTokenizer
: IUrlTokenizer
, IServiceEnabledComponent
34 private readonly IDictionary defaultUrl2CustomUrlInfo
= new HybridDictionary(true);
37 /// Adds the default rule mapping.
40 /// A defautl rule can associate something like a 'default.castle'
41 /// to a controller/action like 'Home/index.castle'
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
)
54 defaultUrl2CustomUrlInfo
[url
] = new UrlInfo(area
, controller
, action
);
57 #region IServiceEnabledComponent
60 /// Services the specified provider.
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
);
78 /// Tokenizes the URL.
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)
98 // // Strip the subdomain from the main domain name
99 // domain = domain.Substring(subdomain.Length);
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
))
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
];
129 controller
= custom
.Controller
;
130 action
= custom
.Action
;
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
);
145 /// Extracts the area controller action.
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];
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)
194 area
= areaSB
.ToString();
199 /// Gets the domain token.
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)
213 if (token
< parts
.Length
)
222 /// Gets the extension of the requested urls page without the preceding period.
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
);
232 return ext
.Substring(1);