Title: Resources [TOC] ## What is a Resource The Resource is one of the central parts of Sling. Extending from JCR's *Everything is Content*, Sling assumes *Everthing is a Resource*. Thus Sling is maintaining a virtual tree of resources, which is a merger of the actual contents in the JCR Repository and resources provided by so called resource providers. By doing this Sling fits very well in the paradigma of the REST architecture. ### Resource Properties Resources have a number of essentiall properties: | Property | Description | |--|--| | Path | Resources are part of a Resource Tree. As such each Resource has a path which is formed by concatenating the names of all Resources along the root to the Resource separated by a slash. Ok, really, this is much like a URL path or a file system path where the slash (`/`) is the separator character. | | Name | The name of the Resource is the last element (or segment) in the path. | | Resource Type | Each resource has a resource type which is used by the Servlet and Script resolver to find the appropriate Servlet or Script to handle the request for the Resource. | | Resource Super Type | The (optional explicit) super type of the Resource. See the section _Resource Types_ below for more details. | | Adapters | Resources are always `Adaptable` and therefore can be adapted to a different view. See the section _Resource Adapters_ below for more details. | | Metadata | Resources in general support [link text][1] providing access to values such as the length of a binary resource (which can be streamed) or the Resource's content type. | For a complete description of the `Resource` interface, please refer to the [link text][2] JavaDoc. ### Resource Types The exact method of setting the resource type for a Resource depends on the actual Resource Provider. For the four main Resource Provider implementations provided by Sling, the assignments are as follows: | Provider | Resource Type | Resource Super Type | |--|--|--| | JCR | The value of the `sling:resourceType` property or the primary node type if the property is not set (a namespace separator colon is replaced by a slash, e.g. the `nt:file` primary node type is mapped to the `nt/file` resource type | The value of the `sling:resourceSuperType` of the Resource node or resource super type of the resource pointed to by the resource type (when accessed with `ResourceResolver.getResource(String)` | | File System | File based resources are of type `nt/file`; folder based resources are of type `nt/folder` corresponding to the respective JCR primary node type | none | | Bundle | File based resources are of type `nt/file`; folder based resources are of type `nt/folder` corresponding to the respective JCR primary node type | none | | Servlet | The absolute path of the resource appended with the suffix `.servlet` | `sling/bundle/resource` | Resource Types form a type hierarchy much like Java classes form a type hierarchy. Each resource type has a resource super type, either explicitly defined as for example for JCR or Servlet Resources or implicitly. The implicit Resource Super Type is at the same time the root Resource Type much like the `java.lang.Object` class is called `sling/servlet/default` (for historical reasons). The `sling/servlet/default` Resource Type is the only type without a super type. ### Adapters The object types to which Resources may be adapted depend mostly depends on the Resource Provider providing the resource. For example all JCR node based resources always adapt to `javax.jcr.Node` objects. If the actual Resource object class implementation extends from the `SlingAdaptable` class, then in addition all `AdapterFactory` services adapting `Resource` objects are considered when trying to adapt the Resource. In general Resource Providers are recommended to have their Resource implementation extend from [link text][3] which guarantees the Resource implementation to extend from `SlingAdaptable` and thus supporting Adapter Factories. ## How to get a Resource To get at Resources, you need a `ResourceResolver`. This interface defines four kinds of methods to access resources: * Absolute Path Mapping Resource Resolution: The `resolve(HttpServletRequest, String)` and `resolve(String)` methods are called to apply some implementation specific path matching algorithm to find a Resource. These methods are mainly used to map external paths - such as path components of request URLs - to Resources. To support creating external paths usable in an URL a third method `map(String)` is defined, which allows for round-tripping. * Absolute or Relative Path Resolution (including search path): The `getResource(String path)` and `getResource(Resource base, String path)` methods may be used to access a resource with an absolute path directly. If it can't be found the path is assumed to be relative and the search path retrieved from `getSearchPath()` is used to retrieve the resource. This mechanism is similar to resolving a programm with the `PATH` environment variable in your favourite operating system. * Resource Enumeration: To enumerate resources and thus iterate the resource tree, the `listChildren(Resource)` method may be used. This method returns an `Iterator` listing all resources whose path prefix is the path of the given Resource. This method will of course also cross boundaries of registered `ResourceProvider` instances to enable iterating the complete resource tree. * Resource Querying: Querying resources is currently only supported for JCR Resources through the `findResources(String query, String language)` and `queryResources(String query, String language)` methods. For more information see the section on [Querying Resources](#querying-resources) below. ### Absolute Path Mapping As has been said, the absolute path mapping methods `resolve(HttpServletRequest, String)` and `resolve(String)` apply some implementation specific path matching algorithm to find a Resource. The difference between the two methods is that the former may take more properties of the `HttpServletRequest` into account when resolving the Resoure, while the latter just has an absolute path to work on. The general algorithm of the two methods is as follows: 1. Call `HttpServletRequest.getScheme(), .getServerName(), getServerPort` to get an absolute path out of the request URL: \[scheme\]({{ refs.scheme.path }})/\[host\].\[port\]\[path\] (`resolve(HttpServletRequest, String)` method only, which) 1. Check whether any virtual path matches the absolute path. If such a match exists, the next step is entered with the match. 1. Apply a list of mappings in order to create a mapped path. The first mapped path resolving to a Resource is assumed success and the Resource found is returned. 1. If no mapping created a mapped path addressing an existing Resource, the method fails and returns a `NonExistingResource` (for the `resolve(String)` and `resolve(HttpServletRequest,String)`) or null (for the `getResource(String path)` and `getResource(Resource base, String path)` methods). The virtual path mapping may be used to create shortcut URLs for otherwise long and complicated URLs. An example of such an URL might be the main administrative page of a CMS system. So, administrators may access the root of the web application and directed to the main administrative page. The path mapping functionality may be used to hide internal resource organization from the request URL space. For example to better control the structure of your repository, you might decide to store all accessible data inside a `/content` subtree. To hide this fact from the users, a mapping may be defined to prefix all incoming paths with `/content` to get at the actual Resource. The `map(String)` applies the path mapping algorithm in the reverse order. That is, first the path mappings are reversed and then any virtual mappings are checked. So, a path `/content/sample` might be mapped `/sample` to revers the `/content` prefixing. Or the main administrative page - say `/system/admin/main.html` \- may be mapped to the virtual URL `/`. More details on mappings can be found at [Mappings for Resource Resolution]({{ refs.mappings-for-resource-resolution.path }}). ### Relative Path Resolution Sometimes it is required to resolve relative paths to Resources. An example of such a use case is Script and Servlet resolution which starts with a relative path consisting of the Resource type, optional selectors and the request extension or method name. By scanning a search path for these relative paths a system provided Resource may be overwritten with some user defined implementation. Consider for example, the system would provide a Servlet to render Resources of type `nt:file`. This Servlet would be registered under the path `/libs/nt/file/html`. For a certain web application, this default HTML rendering might not be appropriate, so a Script is created as `/apps/nt/file/html.jsp` with a customized HTML rendering. By defining the search path to be `[/apps,/libs]` the Servlet resolver would call the `ResourceResolver.getResource(String)` method with the relative path `nt/file/html` and be provided with the first matching resource - `/apps/nt/file/html.jsp` in this example. Of course the search path is not used for absolute path arguments. ### Querying Resources For convenience the `ResourceResolver` provides two Resource querying methods `findResources` and `queryResources` both methods take as arguments a JCR query string and a query language name. These parameters match the parameter definition of the `QueryManager.createQuery(String statement, String language)` method of the JCR API. The return value of these two methods differ in the use case: * `findResources` returns an `Iteratory` of all Resources matching the query. This method is comparable to calling `getNodes()` on the `QueryResult` returned from executing the JCR query. * `queryResources` returns an `Iterator>`. Each entry in the iterator is a `Map