More information
This page is currently a copy from this mailing list thread. See also SLING-387 and the unit test http://svn.apache.org/repos/asf/incubator/sling/trunk/servlets/resolver/src/test/java/org/apache/sling/servlets/resolver/helper/ScriptSelectionTest.java.
This page explains how Sling maps URLs to a script or and servlet. First of all Sling looks up the resource identified by the URL - typically a path inside the JCR repository, which is annotated by the sling:resourceType
property which defines the resource type of that resource. Using this resource type (which is kind of a relative path, eg. "myblog/comment"), scripts or servlets are looked up.
Scripts and servlets are itself resource in Sling and thus have a resource path: this is either the location in the JCR repository, the resource type in a servlet component configuration or the "virtual" bundle resource path (if a script is provided inside a bundle without being installed into the JCR repository).
TODO: explain super types, servlet path mappings, node type resource types (my:type -> my/type
)
(0) Fundamental: Scripts and Servlets are equal
In the following discussion, I will write about scripts. This will always include servlets as well. In fact, internally, Sling only handles with Servlets, whereas scripts are packed inside a Servlet wrapping and representing the script.
(I) Base: Resource Type Inheritance
While not exactly part of our discussion, resource type inheritance as implemented for SLING-278 plays a vital role in script resolution.
Each resource type may have a resource super type, which may be defined in various ways. One example is having a sling:resourceSuperType
property in the node addressed by the resource type. See http://www.mail-archive.com/sling-dev@incubator.apache.org/msg02365.html and SLING-278 for more details.
If a resource type has no explicit resource super type, the resource super type is assumed to be "sling/servlet/default". That is the resource type used for default script selection is also acting as a basic resource type much like java.lang.Object does for other types in the Java language.
(II) Script Locations
Scripts are looked up in a series of locations defined by the ResourceResolver.getSearchPath() and the resource type (and resource super types) of the requested resource:
{scriptPathPrefix}/{resourceTypePath}
The pseudo code for iterating the locations would be something like:
var type = resource.getResourceType(); while (type != null) { for (String root: resourceResolver.getSearchPath()) { String path = root + type.toPath(); findScriptsIn(path); } if (type == defaultServlet) { type = null; } else { type = getResourceSuperType(type); if (type == null) { type = defaultServlet; } } }
(III) All requests are NOT equal
GET and HEAD request methods are treated differently than the other request methods. Only for GET and HEAD requests will the request selectors and extension be considered for script selection. For other requests the servlet or script name (without the script extension) must exactly match the request method.
That is for a PUT request, the script must be PUT.esp or PUT.jsp. For a GET request with a request extension of html, the script name may be html.esp or GET.esp.
(IV) Scripts for GET requests
Apart for supporting scripts named after the request method, scripts handling GET and HEAD requests may be named differently for Sling to support a more elaborate processing order.
Depending on whether request selectors are considered, a script may have two forms:
- a. Ignoring request selectors (e.g. there are none in the request URI)
{resourceTypeLabel}.{requestExtension}.{scriptExtension}
- b. Handling request selectors
{selectorStringPath}.{requestExtension}.{scriptExtension}
The constituents of these script names are as follows:
- {
resourceTypeLabel
} - The last path segment of the path created from the resource type. This part is optional if the {requestExtension
} is used in the script name. - {
requestExtension
} - The request extension. This part may be ommitted if the request extension is "html", otherwise this part is required. If this part is ommitted, the {resourceTypeLabel
} is required in the case of ignoring the selectors. - {
scriptExtension
} - The extension, e.g. "esp" or "jsp", identifying the scripting langauage used. - {
selectorStringPath
} - The selector string converted to a path, along the lines ofselectorString.replace('.', '/')
.
(V) Priority
The rules for script path priorization is defined as follows:
- The more request selectors are matched, the better
- A script including the request extension matches better than one without a request extension (for html only)
- A script found earlier matches better than a script found later in the processing order. This means, that script closer to the original resource type in the resource type hierarchy is considered earlier.
(VI) Examples
Taking up again the list of potential script paths for a request of a resource whose resource type is sling:sample and the request selectors are "print.a4" and the request extension is "html" could be:
- (0) GET.esp
- (1) sample.esp
- (2) html.esp
- (3) print.esp
- (4) print/a4.esp
- (5) print.html.esp
- (6) print/a4.html.esp
The priority of script selection would (6) - (4) - (5) - (3) - (2) - (1) - (0). Note that (4) is a better match than (5) because it matches more selectors even though (5) has an extension match where (4) does not.