Page Edited :
SLING :
Flexible Resource Resolution
Flexible Resource Resolution has been edited by Felix Meschberger (Nov 25, 2008). Content:Flexible Resource ResolutionStatus: DRAFT IntroductionCurrently the resource resolver has a limited set of options to resolve incoming requests to resources and to map resource paths to paths to be used in links in the response:
To implement SLING-249 I initially proposed
After an internal discussion I proposed a modified implementation Roy Fielding noted This page is about trying to write up the fine print in this proposal and also document the actual implementation. Goals
JCR EnvironmentPropertiesWhen dealing with the new resource resolution we have a number of properties influencing the process:
Node TypesTo ease with the definition of redirects and aliases, the following node types are defined:
Note, that these node types only help setting the properties. The implementation itself only cares for the properties and their values and not for any of these node types. Root Level MappingsRoot Level Mappings apply to the request at large including the scheme, host.port and uri path. To accomplish this a path is constructed from the request as {scheme}/{host.port}/{uri_path}. This string is then matched against mapping entries below /etc/map which are structured in the content analogously. The longest matching entry string is used and the replacement, that is the redirection property, is applied. Mapping Entry SpecificationEach entry in the mapping table is a regular _expression_, which is constructed from the resource path below /etc/map. If any resource along the path has a sling:match property, the respective value is used in the corresponding segment instead of the resource name. Only resources either having a sling:redirect or sling:internalRedirect property are used as table entries. Other resources in the tree are just used to build the mapping structure. Example Consider the following content /etc/map +-- http +-- example.com.80 +-- sling:redirect = "http://www.example.com/" +-- www.example.com.80 +-- sling:internalRedirect = "/example" +-- any_example.com.80 +-- sling:match = ".+\.example\.com\.80" +-- sling:redirect = "http://www.example.com/" +-- localhost_any +-- sling:match = "localhost\.\d*" +-- sling:internalRedirect = "/content" +-- cgi-bin +-- sling:internalRedirect = "/scripts" +-- gateway +-- sling:internalRedirect = "http://gbiv.com" +-- (stories) +-- sling:internalRedirect = "/anecdotes/$1"
Regular _expression_ matchingAs said above the mapping entries are regular expressions which are matched against path. As such these regular expressions may also contain capturing groups as shown in the example above: http/localhost\.\d*/(stories). After matching the path against the regular _expression_, the replacement pattern is applied which allows references back to the capturing groups. To illustrate the matching and replacement is applied according to the following pseudo code: String path = request.getScheme + "/" + request.getServerName() + "." + request.getServerPort() + "/" + request.getPathInfo(); String result = null; for (MapEntry entry: mapEntries) { Matcher matcher = entry.pattern.matcher(path); if (matcher.find()) { StringBuffer buf = new StringBuffer(); matcher.appendReplacement(buf, entry.getRedirect()); matcher.appendTail(buf); result = buf.toString(); break; } } At the end of the loop, result contains the mapped path or null if no entry matches the request path. Redirection ValuesThe result of matching the request path and getting the redirection is either a path into the resource tree or another URL. If the result is an URL, it is converted into a path again and matched against the mapping entries. This may be taking place repeatedly until an absolute or relative path into the resource tree results. The following pseudo code summarizes this behaviour: String path = ....; String result = path; do { result = applyMapEntries(result); } while (isURL(result)); As soon as the result of applying the map entries is an absolute or relative path (or no more map entries match), Root Level Mapping terminates and the next step in resource resolution, resource tree access, takes place. Resource Tree AccessThe result of Root Level Mapping is an absolute or relative path to a resource. If the path is relative – e.g. myproject/docroot/sample.gif – the resource resolver search path (ResourceResolver.getSearchPath() is used to build absolute paths and resolve the resource. In this case the first resource found is used. If the result of Root Level Mapping is an absolute path, the path is used as is. Accessing the resource tree after applying the Root Level Mappings has four options:
Drilling Down the Resource TreeDrilling down the resource tree starts at the root and for each segement in the path checks whether a child resource of the given name exists or not. If not, a child resource is looked up, which has a sling:alias property whose value matches the given name. If neither exists, the search is terminated and the resource cannot be resolved. The following pseudo code shows this algorithm assuming the path is absolute: String path = ...; // the absolute path Resource current = getResource("/"); String[] segements = path.split("/"); for (String segment: segments) { Resource child = getResource(current, segement); if (child == null) { Iterator<Resource> children = listChildren(current); current = null; while (children.hasNext()) { child = children.next(); if (segment.equals(getSlingAlias(child))) { current = child; break; } } if (current == null) { // fail break; } } else { current = child; } } |
Unsubscribe or edit your notifications preferences