incubator-sling-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From fmesc...@apache.org
Subject svn commit: r1328899 [7/8] - in /sling/site/trunk: content/ templates/
Date Sun, 22 Apr 2012 16:52:16 GMT
Added: sling/site/trunk/content/servlet-resolution.mdtext
URL: http://svn.apache.org/viewvc/sling/site/trunk/content/servlet-resolution.mdtext?rev=1328899&view=auto
==============================================================================
--- sling/site/trunk/content/servlet-resolution.mdtext (added)
+++ sling/site/trunk/content/servlet-resolution.mdtext Sun Apr 22 16:52:13 2012
@@ -0,0 +1,306 @@
+Title: Servlet Resolution
+<a name="ServletResolution-ServletResolution"></a>
+# Servlet Resolution
+
+{warning:title=Out Of Sync}
+Please note that the description on this page is out of sync with the most
+recent developments going on as part of implementing issue [SLING-387](https://issues.apache.org/jira/browse/SLING-387)
+. See the links to integration tests at the end of this page for the
+Current Truth.
+
+Please see the new [Servlets](servlets.html)
+ page.
+{warning}
+
+{toc:minLevel=2}
+
+
+<a name="ServletResolution-ServletsareResources"></a>
+## Servlets are Resources
+
+As explained on the [Resources](resources.html)
+ page, the Resource is the central data abstraction of Sling. In this
+contexts, Servlets are of course also povided as Resources. As such
+Servlets may be enumerated by iterating the Resource tree and Servlets may
+be retrieved through the *ResourceResolver*.
+
+To show a Servlet inside the Resource tree, the *sling/servlet-resolver*
+project provides a *ServletResourceProvider* implementing the
+*ResourceProvider* interface. For each Servlet registered as an OSGi
+service with one or more defined service reference properties a
+*ServletResourceProvider* instance is registered.
+
+The following service reference properties are defined for Servlets defined
+as OSGi services of type *javax.servlet.Servlet*:
+
+<table>
+<tr><th> Name </th><th> Description </th></tr>
+<tr><td> *sling.servlet.paths* </td><td> A list of absolute paths under which the
+servlet is accessible as a Resource. The property value must either be a
+single String, an array of Strings or a Vector of Strings. </td></tr>
+<tr><td> *sling.servlet.resourceTypes* </td><td> The resource type(s) supported by the
+servlet. The property value must either be a single String, an array of
+Strings or a Vector of Strings. This property is ignored if the
+*sling.servlet.paths* property is set. </td></tr>
+<tr><td> *sling.servlet.selectors* </td><td>  The request URL selectors supported by the
+servlet. The selectors must be configured as they would be specified in the
+URL that is as a list of dot-separated strings such as <em>print.a4</em>.
+The property value must either be a single String, an array of Strings or a
+Vector of Strings. This property is ignored if the *sling.servlet.paths*
+property is set. </td></tr>
+<tr><td> *sling.servlet.extensions* </td><td> The request URL extensions supported by
+the servlet for GET requests. The property value must either be a single
+String, an array of Strings or a Vector of Strings. This property is
+ignored if the *sling.servlet.paths* property is set. </td></tr>
+<tr><td> *sling.servlet.methods* </td><td>  The request methods supported by the
+servlet. The property value must either be a single String, an array of
+Strings or a Vector of Strings. This property is ignored if the
+*sling.servlet.paths* property is set. </td></tr>
+<tr><td> *sling.servlet.prefix* </td><td>  The absolute prefix to make relative paths
+absolute. This property is a String and is optional. If it is not set, the
+actual prefix used is derived from the search path of the
+*ResourceResolver* at the time of registration. </td></tr>
+</table>
+
+
+For a Servlet registered as an OSGi service to be used by the Sling Servlet
+Resolver, the following restrictions apply:
+
+1. Either the *sling.servlet.paths* or the
+*sling.servlet.resourceTypes* service reference property must be set. If
+neither is set, the Servlet service is ignored.
+1. If the *sling.servlet.paths* property is set, all other
+*sling.servlet.** properties are ignored.
+1. Otherwise a Resource provider is registered for the Servlet for each
+permutation resource types, selectors, extensions and methods.
+
+
+Each path to be used for registration -- either from the
+*sling.servlet.paths* property or constructed from the other
+*sling.servlet.** properties -- must be absolute. Any relative path is
+made absolute by prefixing it with a root path. This prefix may be set with
+the *sling.servlet.prefix* service registration property. If this
+property is not set, the first entry in the *ResourceResolver* search
+path for the *ResourceResolver.getResource(String)* method is used as the
+prefix. If this entry cannot be derived, a simpe slash -- */* -- is used
+as the prefix.
+
+
+<a name="ServletResolution-Example:RegistrationbyPath"></a>
+### Example: Registration by Path
+
+
+    sling.servlet.paths = [ "/libs/sling/sample/html", "/libs/sling/sample/txt" ]
+    sling.servlet.resourceTypes = [ "sling/unused" ]
+    sling.servlet.selectors = [ "img" ]
+    sling.servlet.extensions = [ "html", "txt", "json" ]
+
+
+A Servlet service registered with these properties is registered under the
+following paths:
+
+   * */libs/sling/sample/html*
+   * */libs/sling/sample/txt*
+
+The registration properties *sling.servlet.resourceTypes*,
+*sling.servlet.selectors* and *sling.servlet.extensions* are ignored
+because the *sling.servlet.paths* property is set.
+
+
+<a name="ServletResolution-Example:RegistrationbyResourceTypeetc."></a>
+### Example: Registration by Resource Type etc.
+
+
+    sling.servlet.resourceTypes = [ "sling/unused" ]
+    sling.servlet.selectors = [ "img", "tab" ]
+    sling.servlet.extensions = [ "html", "txt", "json" ]
+
+
+A Servlet service registered with these properties is registered under the
+following paths:
+
+   * *_prefix_/sling/unused/img/html*
+   * *_prefix_/sling/unused/img/txt*
+   * *_prefix_/sling/unused/img/json*
+   * *_prefix_/sling/unused/tab/html*
+   * *_prefix_/sling/unused/tab/txt*
+   * *_prefix_/sling/unused/tab/json*
+
+As explained the script is registered for each permutation of the resource
+types, selectors and extension. See above For an explanation of how
+*_prefix_* is defined.
+
+
+<a name="ServletResolution-ScriptsareServlets"></a>
+## Scripts are Servlets
+
+
+The Sling API defines a *SlingScript* interface which is used to
+represent (executable) scripts inside of Sling. This interface is
+implemented in the *scripting/resolver* bundle in the
+*DefaultSlingScript* class which also implements the
+*javax.servlet.Servlet*.
+
+To further simplify the access to scripts from the Resource tree, the
+*scripting/resolver* bundle registers an *AdapterFactory* to adapt
+Resources to Scripts and Servlets. In fact the adapter factory returns
+instances of the *DefaultSlingScript* class for both Scripts and
+Servlets.
+
+This functionality is used by the *ServletResolver.resolveServlet*
+implementation in the *sling/servlet-resolver* bundle: This
+implementation just looks up any Resource in the resource tree according
+its lookup algorithm (see below). The first matching Resource adapting to a
+*javax.servlet.Servlet* is used for processing the resource.
+
+So from the perspective of the Servlet resolver, scripts and servlets are
+handled exactly the same.
+
+
+<a name="ServletResolution-ResolutionProcess"></a>
+## Resolution Process
+
+The Servlet Resolution Process four elements of a
+*SlingHttpServletRequest*:
+
+1. The _resource type_ as retrieved through
+*request.getResource().getResourceType()*. Because the resource type may
+be a node type such as _nt:file_, the resource type is mangled into a path
+by replacing any colons contained to forward slashs. Also, any backslashes
+contained are replaced to forward slashes. This should give a relative
+path. Of course a resource type may also be set to an absolute path. See
+below.
+1. The _request selectors_ as retrieved through
+*request.getRequestPathInfo().getSelectorString()*. The selector string
+is turned into a realtive path by replacing all separating dots by forward
+slashes. For example the selector string *print.a4* is  converted into
+the relative path *print/a4*.
+1. The _request extension_ as retrieved through
+*request.getRequestPathInfo().getExtension()* if the request method is
+_GET_ or _HEAD_ and the request extension is not empty.
+1. The _request method name_ for any request method except _GET_ or
+_HEAD_ or if the request extension is empty.
+
+The _resource type_ is used as a (relative) parent path to the Servlet
+while the _request extension_ or _request method_ is used as the Servlet
+(base) name. The Servlet is retrieved from the Resource tree by calling the
+*ResourceResolver.getResource(String)* method which handles absolute and
+relative paths correctly by searching realtive paths in the configured
+search path.
+
+The pseudo-code for Servlet resolution is as follows:
+
+
+    Servlet resolveServlet(SlingHttpServletRequest request) {
+    
+        String resourceType = request.getResource().getResourceType();
+        resourceType = resourceType.replaceAll("\\:", "/");
+    
+        String baseName;
+        if (("GET".equals(request.getMethod()) ||
+"HEAD".equals(request.getMethod())
+    	    && request.getRequestPathInfo().getExtension() != null) {
+    	baseName = request.getRequestPathInfo().getExtension();
+        } else {
+    	baseName = request.getMethod();
+        }
+    
+        if (request.getRequestPath().getSelectorString() != null) {
+    	String selectors = request.getRequestPath().getSelectorString();
+    	selectors = selectors.replace('.', '/');
+    	while (selectors != null) {
+    	    String path = resourceType + "/" + selectors + "/" + baseName;
+    	    Servlet servlet = findServletFor(path);
+    	    if (servlet != null) {
+    		return servlet;
+    	    }
+    
+    	    int lastSlash = selectors.lastIndexOf('/');
+    	    if (lastSlash > 0) {
+    		selectors = selectors.substring(0, lastSlash);
+    	    } else {
+    		selectors = null;
+    	    }
+    	}
+        }
+            
+        String path = resourceType + "/" + baseName;
+        return findScriptFor(path);
+    }
+    
+    Servlet findScriptFor(path) {
+        // Find a Servlet or Script with the given path in the search path
+        // where the Script is allowed to have Script language specific
+        // extension, such as .js, .jsp, etc.
+    }
+
+
+
+<a name="ServletResolution-DefaultServlet(s)"></a>
+## Default Servlet(s)
+
+As explained in the Resolution Process section above, a default Servlet is
+selected if no servlet for the current resource type can be found. To make
+the provisioning of a default Servlet as versatile as provisioning per
+resource type Servlets (or scripts), the default Servlet is selected with
+just a special resource type *sling/servlet/default*.
+
+The actual Servlet or Script called as the default Servlet is resolved
+exactly the same way as for any resource type. That is, also for the
+default Servlet selection, the request selectors and extension or method
+are considered. Also, the Servlet may be a Servlet registered as an OSGi
+service and provided through a Servlet Resource provider or it may be a
+Script stored in the repository or provided by the bundle.
+
+Finally, if not even a registered default Servlet may be resolved for the
+request, because none has been registered, the *sling/servlet-resolve*
+bundle provides a fall back *DefaultServlet* with the following
+functionality:
+
+   * If the request has no extension and the Resource of the request adapts
+to an *InputStream*, the contents of the resoure is stream out as the
+response. The response content type is taken from the *sling.contentType*
+Resource meta data or derived from the Resource path. If the
+*sling.characterEncoding* Resource meta data property is set, that value
+is used as the response character encoding. Currently there is no ETag and
+modification time stamp support.
+   * Otherwise if the object has an OCM mapping, the properties of the
+mapped object are printed.
+   * Otherwise just the path of the Resource is printed.
+
+
+<a name="ServletResolution-ErrorHandlerServlet(s)"></a>
+## Error Handler Servlet(s)
+
+The *sling/servlet-resolver* project also provides an implementation of
+the Sling Core *ErrorHandler* interface, which applies the same Servlet
+resolution process as used for normal request processing. Error handler
+Servlets and Scripts are looked up with the predefined resource
+*sling/servlet/errorhandler* and an error specific name:
+
+   * *HTTP Status Code Handling*: To handle HTTP status code as used by the
+*HttpServletResponse.sendError* methods, status code is used as the
+Servlet name. For example to provide a handler for status code 404
+(NOT_FOUND), you could create a script
+*prefix/sling/servlet/errorhandler/404.esp* or for a status code 500
+(INTERNAL_SERVER_ERRROR), you might want to register a Servlet at
+*prefix/sling/servlet/errorhandler/500*.
+   * *Throwable Handling*: To handle uncaught *Throwables* the simple
+name of the *Throwable* class is used as the Servlet name. Similarly to
+the Java *try-catch* clauses the class hierarchy is supported. That is to
+handle an uncaught *FileNotFoundException*, the names
+*FileNotFoundException*, *IOException*, *Exception*, *Throwable*
+are checked for a Servlet and the first one found is then used. Again, the
+Serlvet may be a Servlet registered as an OSGi service or may be a plain
+script stored in the JCR repository or provided through some custom
+Resource provider.
+
+<a name="ServletResolution-Integrationtests"></a>
+## Integration tests
+A set of simple example servlets is available in the [launchpad/test-services module](http://svn.apache.org/repos/asf/incubator/sling/trunk/launchpad/test-services)
+. 
+
+Integration tests in the [launchpad/testing module](http://svn.apache.org/repos/asf/incubator/sling/trunk/launchpad/testing/src/test/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/resolution)
+ verify that these examples are correct.
+
+Contributions to these tests and examples are welcome, of course!

Added: sling/site/trunk/content/servlets.mdtext
URL: http://svn.apache.org/viewvc/sling/site/trunk/content/servlets.mdtext?rev=1328899&view=auto
==============================================================================
--- sling/site/trunk/content/servlets.mdtext (added)
+++ sling/site/trunk/content/servlets.mdtext Sun Apr 22 16:52:13 2012
@@ -0,0 +1,200 @@
+Title: Servlets
+<a name="Servlets-ServletsandScripts"></a>
+# Servlets and Scripts
+
+Servlets can be registered as OSGi services. The following service
+reference properties are defined for Servlets defined as OSGi services of
+type *javax.servlet.Servlet*:
+
+<table>
+<tr><th> Name </th><th> Description </th></tr>
+<tr><td> *sling.servlet.paths* </td><td> A list of absolute paths under which the
+servlet is accessible as a Resource. The property value must either be a
+single String, an array of Strings or a Vector of Strings. </td></tr>
+<tr><td> *sling.servlet.resourceTypes* </td><td> The resource type(s) supported by the
+servlet. The property value must either be a single String, an array of
+Strings or a Vector of Strings. This property is ignored if the
+*sling.servlet.paths* property is set. </td></tr>
+<tr><td> *sling.servlet.selectors* </td><td> The request URL selectors supported by the
+servlet. The selectors must be configured as they would be specified in the
+URL that is as a list of dot-separated strings such as <em>print.a4</em>.
+The property value must either be a single String, an array of Strings or a
+Vector of Strings. This property is ignored if the *sling.servlet.paths*
+property is set. </td></tr>
+<tr><td> *sling.servlet.extensions* </td><td> The request URL extensions supported by
+the servlet for requests. The property value must either be a single
+String, an array of Strings or a Vector of Strings. This property is
+ignored if the *sling.servlet.paths* property is set. </td></tr>
+<tr><td> *sling.servlet.methods* </td><td> The request methods supported by the servlet.
+The property value must either be a single String, an array of Strings or a
+Vector of Strings. This property is ignored if the *sling.servlet.paths*
+property is set. If this property is missing, the value defaults to GET,
+regardless of which methods are actually implemented/handled by the
+servlet.</td></tr>
+<tr><td> *sling.servlet.prefix* </td><td> The prefix or numeric index to make relative
+paths absolute. If the value of this property is a number (int), it defines
+the index of the search path entries from the resource resolver to be used
+as the prefix. The defined search path is used as a prefix to mount this
+servlet. The number can be -1 which always points to the last search entry.
+If the specified value is higher than than the highest index of the search
+paths, the last entry is used. The index starts with 0. If the value of
+this property is a string and parseable as a number, the value is treated
+as if it would be a number. If the value of this property is a string
+starting with "/", this value is applied as a prefix, regardless of the
+configured search paths! If the value is anything else, it is ignored. If
+this property is not specified, it defaults to the default configuration of
+the sling servlet resolver. </td></tr>
+</table>
+
+A *SlingServletResolver* listens for *Servlet{*}services and - given
+the correct service registration properties - provides the servlets as
+resources in the (virtual) resource tree. Such servlets are provided as
+*ServletResource* instances which adapt to the *javax.servlet.Servlet*
+class.
+
+For a Servlet registered as an OSGi service to be used by the Sling Servlet
+Resolver, the either or both of the *sling.servlet.paths* or the
+*sling.servlet.resourceTypes* service reference properties must be set.
+If neither is set, the Servlet service is ignored.
+
+Each path to be used for registration - either from the
+*sling.servlet.paths* property or constructed from the other
+*sling.servlet.\** properties - must be absolute. Any relative path is
+made absolute by prefixing it with a root path. This prefix may be set with
+the *sling.servlet.prefix* service registration property. If this
+property is not set, the first entry in the *ResourceResolver* search
+path for the *ResourceResolver.getResource(String)* method is used as the
+prefix. If this entry cannot be derived, a simpe slash - */* \- is used
+as the prefix.
+
+If *sling.servlet.methods* is not specified, the servlet is only
+registered for handling GET requests. Make sure to list all methods you
+want to be handled by this servlet.
+
+<a name="Servlets-Automatedtests"></a>
+### Automated tests
+The [launchpad/test-services](http://svn.apache.org/repos/asf/sling/trunk/launchpad/test-services/)
+ module contains test servlets that use various combinations of the above
+properties. 
+
+The [launchpad/integration-tests](http://svn.apache.org/repos/asf/sling/trunk/launchpad/integration-tests/)
+ module contains a number of tests (like the [ExtensionServletTest|http://svn.apache.org/repos/asf/sling/trunk/launchpad/integration-tests/src/main/java/org/apache/sling/launchpad/webapp/integrationtest/servlets/resolution/ExtensionServletTest.java]
+ for example) that verify the results.
+
+Such tests run as part of our continuous integration process, to
+demonstrate and verify the behavior of the various servlet registration
+mechanisms, in a way that's guaranteed to be in sync with the actual Sling
+core code. If you have an idea for additional tests, make sure to let us
+know!
+
+<a name="Servlets-Example:RegistrationbyPath"></a>
+### Example: Registration by Path
+
+
+    sling.servlet.paths = \[ "/libs/sling/sample/html", "/libs/sling/sample/txt" \]
+    sling.servlet.resourceTypes = \[ "sling/unused" \]
+    sling.servlet.selectors = \[ "img" \]
+    sling.servlet.extensions = \[ "html", "txt", "json" \]
+
+
+A Servlet service registered with these properties is registered under the
+following paths:
+
+* */libs/sling/sample/html*
+* */libs/sling/sample/txt*
+
+The registration properties *sling.servlet.resourceTypes*,
+*sling.servlet.selectors* and *sling.servlet.extensions* *are ignored*
+because the *sling.servlet.paths* property is set.
+
+
+<a name="Servlets-Example:RegistrationbyResourceTypeetc."></a>
+### Example: Registration by Resource Type etc.
+
+
+    sling.servlet.resourceTypes = \[ "sling/unused" \]
+    sling.servlet.selectors = \[ "img", "tab" \]
+    sling.servlet.extensions = \[ "html", "txt", "json" \]
+
+
+A Servlet service registered with these properties is registered under the
+following paths:
+
+* *{_}prefix_/sling/unused/img/html*
+* *{_}prefix_/sling/unused/img/txt*
+* *{_}prefix_/sling/unused/img/json*
+* *{_}prefix_/sling/unused/tab/html*
+* *{_}prefix_/sling/unused/tab/txt*
+* *{_}prefix_/sling/unused/tab/json*
+
+As explained the Servlet is registered for each permutation of the resource
+types, selectors and extension. See above For an explanation of how
+*{_}prefix{_*} is defined.
+
+
+<a name="Servlets-ScriptsareServlets"></a>
+## Scripts are Servlets
+
+
+The Sling API defines a *SlingScript* interface which is used to
+represent (executable) scripts inside of Sling. This interface is
+implemented in the *scripting/core* bundle in the *DefaultSlingScript*
+class which also implements the *javax.servlet.Servlet*.
+
+To further simplify the access to scripts from the Resource tree, the
+*scripting/core* bundle registers an *AdapterFactory* to adapt
+Resources to Scripts and Servlets (the *SlingScriptAdapterFactory*). In
+fact the adapter factory returns instances of the *DefaultSlingScript*
+class for both Scripts and Servlets.
+
+From the perspective of the Servlet resolver, scripts and servlets are
+handled exactly the same. In fact, internally, Sling only handles with
+Servlets, whereas scripts are packed inside a Servlet wrapping and
+representing the script.
+
+
+<a name="Servlets-"></a>
+## 
+
+
+<a name="Servlets-DefaultServlet(s)"></a>
+## Default Servlet(s)
+
+As explained in the Resolution Process section above, a default Servlet is
+selected if no servlet (or script) for the current resource type can be
+found. To make the provisioning of a default Servlet as versatile as
+provisioning per resource type Servlets (or scripts), the default Servlet
+is selected with just a special resource type *sling/servlet/default*.
+
+The actual Servlet or Script called as the default Servlet is resolved
+exactly the same way as for any resource type. That is, also for the
+default Servlet selection, the request selectors and extension or method
+are considered. Also, the Servlet may be a Servlet registered as an OSGi
+service or it may be a Script stored in the repository or provided by any
+bundle.
+
+Finally, if not even a registered default Servlet may be resolved for the
+request, because none has been registered, the *servlets/resolver* bundle
+provides a fall back the *DefaultServlet* with the following
+functionality:
+
+* If an *NonExistingResource* was created for the request the
+*DefaultServlet* sends a 404 (Not Found)
+* Otherwise the *DefaultServlet* sends a 500 (Internal Server Error),
+because normally at least a *NonExistingResource* should be created
+
+<a name="Servlets-OptingServletinterface"></a>
+## OptingServlet interface
+If a registered servlet implements the OptingServlet interface, Sling uses
+that servlet's *accepts(SlingHttpServletRequest request)* method to
+refine the servlet resolution process.
+
+In this case, the servlet is only selected for processing the current
+request if its *accept* method returns true.
+
+
+<a name="Servlets-ErrorHandlerServlet(s)orScripts"></a>
+## Error Handler Servlet(s) or Scripts
+
+Error handling support is now described on the [Errorhandling](errorhandling.html)
+ page.

Added: sling/site/trunk/content/sling-api.mdtext
URL: http://svn.apache.org/viewvc/sling/site/trunk/content/sling-api.mdtext?rev=1328899&view=auto
==============================================================================
--- sling/site/trunk/content/sling-api.mdtext (added)
+++ sling/site/trunk/content/sling-api.mdtext Sun Apr 22 16:52:13 2012
@@ -0,0 +1,560 @@
+Title: Sling API
+<a name="SlingAPI-TheSlingAPI"></a>
+# The Sling API
+
+
+{note:title=Work In Progress}
+The contents of this page is being created at the moment. It contains
+incomplete and partially wrong information as the text is adapted from the
+contents of the [Component API](component-api.html)
+ documentation page.
+{note}
+
+
+<a name="SlingAPI-Introduction"></a>
+## Introduction
+
+The _Sling API_ defines a presentation framework to build Web Applications.
+As such the Sling API builds upon the Servlet API but extends the latter
+with new functionality:
+
+* A web page may be built from many different pieces. This aggregation of
+different pieces is comparable to the functionality provided by the Portlet
+API. In contrast to the latter, though, the pieces may themselves be
+aggregates of yet more pieces. So a single web page response may consist of
+a tree of pieces.
+* Just like the Servlet API and the Portlet API the Sling API mainly
+defines a Java based framework. Yet the Sling API comes with the intention
+of supporting scripting built.
+* In contrast to the Servlet API and the Portlet API, the Sling API is
+resource centric. That is, the request URL does not address a servlet or a
+portlet but a resource represented by an instance of the
+*org.apache.sling.api.resource.Resource* interface. From this resource
+the implementation of the Sling API will derive a *javax.servlet.Servlet*
+or *org.apache.sling.api.scripting.SlingScript* instance, which is used
+to handle the request.
+
+An implementation of the presentation framework defined by the Sling API is
+called a _Sling Framework_. The Apache Sling project actually contains two
+implementations of this API: _microsling_ and _Sling_. microsling (note the
+lowercase _m_) implements the same request processing mechanisms as _Sling_
+but is very hardcoded. It serves well as a rapid development environment as
+it is quickly set up, easy to handle and shows results very easily. Sling
+on the other hand is based on an OSGi framework and very flexible, allowing
+the extension of the system in various ways.
+
+
+
+<a name="SlingAPI-GoingResourceCentric"></a>
+## Going Resource Centric
+
+Traditional web applications are built around the notion of a traditional
+application which is converted into an application which may be used using
+a Web Browser. Web applications consist of a series of servlets and JSP
+scripts, which are called based on configuration in the web application
+deployment descriptor. Such applications are generally based on some
+internal database or some static filesystem content.
+
+The Sling API on the other hand looks more like a traditional web server
+from the outside, which delivers more or less static content. Thus, while
+the traditional web application uses the request URL to select a piece of
+code to execute, the Sling API uses the URL to select a resource to be
+delivered.
+
+
+
+<a name="SlingAPI-ComparsiontotheServletAPI"></a>
+### Comparsion to the Servlet API
+
+The Sling API builds upon the Servlet API. Generally a Sling Framework will
+run inside a Servlet Container and be manifested towards the Servlet
+Container as a single Servlet, which dispatches requests to the Servlets
+and Scripts depending on the request URLs.
+
+Response rendering may itself be a multi-step operation. Depending on the
+Servlets and Scripts, the rendering may include dispatching for child (or
+even foreign) Resources.
+
+
+
+<a name="SlingAPI-ComparisiontothePortletAPI"></a>
+### Comparision to the Portlet API
+
+Unlike the Portlet API, which defines one single level of portlet hierarchy
+- portlets are just pieces residing besides each other - the Sling API
+allows for hierarchic structuring of Resources and hence Servlet and Script
+renderings. To support this structuring, the Sling Framework does not
+control the rendering process of all elements on the page like the Portlet
+Container does for the portlets. Instead only the Resource addressed by the
+request URL is processed and it is left to the Servlet or Script rendering
+that Resource to dispatch other Resource/Servlet/Script tupels to add more
+data to the response.
+
+
+<a name="SlingAPI-ToIteratororToEnumeration"></a>
+### To Iterator or To Enumeration
+
+With the advent of the Java Collection framework in Java 2, the
+*Enumeration* has been superceded by the *Iterator*. So the natural
+choice for the Sling API for methods to return enumeratable collection of
+objects would have be to declare the use of *Iterator* instances. But
+because the Servlet API defines to use *Enumeration* instances, the Sling
+API will also declare the use of *Enumeration* instances for consistency
+with the Servlet API extended by the Sling API.
+
+
+
+
+<a name="SlingAPI-RequestProcessing"></a>
+## Request Processing
+
+Unlike traditional Servlet API request processing, a Sling API request is
+processed by the Sling Framework in three basic steps:
+
+1. *Resource Resolution* - The Sling Framework derives a Resource instance
+from the client request URL. The details of how to resolve the Resource.
+One possible solution would be to map the request URL to a [Java Content Repository](http://www.jcp.org/en/jsr/detail?id=170)
+ Node and return a Resource representing that Node.
+1. *Servlet and Script Resolution* - From the Resource created in the first
+step, the Servlet or Script is resolved based on the type of the Resource.
+The resource type is a simple string, whose semantics is defined by the
+Sling Framework. One possible definition could be for the resource type to
+be the primary node type of the Node underlying the Resource.
+1. *Input Processing and Response Generation* -	After getting the Resource
+and the Servlet or Script, the *service()* method is called or the script
+is evaluated to process any user supplied input and send the response to
+the client. To structure the rendered response page, this method is
+responsible to include other resources. See _Dispatching Requests_ below
+for details. See _Error Handling_ below for a discussion on how exceptions
+and HTTP stati are handled.
+
+
+
+<a name="SlingAPI-URLdecomposition"></a>
+### URL decomposition
+
+During the _Resource Resolution_ step, the client request URL is decomposed
+into the following parts:
+
+1. *Resource Path* -  The longest substring of the request URL resolving to
+a Resource such that the resource path is either the complete request URL
+or the next character in the request URL after the resource path is either
+a dot (*.*) or a slash (*/*).
+1. *Selectors* -  If the first character in the request URL after the
+resource path is a dot, the string after the dot upto but not including the
+last dot before the next slash character or the end of the request URL. If
+the resource path spans the complete request URL or if a slash follows the
+resource path in the request URL, no seletors exist. If only one dot
+follows the resource path before the end of the request URL or the next
+slash, no selectors exist.
+1. *Extension* -  The string after the last dot after the resource path in
+the request URL but before the end of the request URL or the next slash
+after the resource path in the request URL. If a slash follows the resource
+path in the request URL, the extension is empty.
+1. *Suffix Path* -  If the request URL contains a slash character after the
+resource path and optional selectors and extension, the path starting with
+the slash upto the end of the request URL is the suffix path. Otherwise,
+the suffix path is empty.
+
+*Examples*: Assume there is a Resource at */a/b*, which has no children.
+
+<table>
+<tr><th> URI </th><th> Resource Path </th><th> Selectors </th><th> Extension </th><th> Suffix </th></tr>
+<tr><td> /a/b			    </td><td> /a/b </td><td> null  </td><td> null </td><td> null       </td></tr>
+<tr><td> /a/b.html		    </td><td> /a/b </td><td> null  </td><td> html </td><td> null       </td></tr>
+<tr><td> /a/b.s1.html		    </td><td> /a/b </td><td> s1    </td><td> html </td><td> null       </td></tr>
+<tr><td> /a/b.s1.s2.html	    </td><td> /a/b </td><td> s1.s2 </td><td> html </td><td> null       </td></tr>
+<tr><td> /a/b/c/d		    </td><td> /a/b </td><td> null  </td><td> null </td><td> /c/d       </td></tr>
+<tr><td> /a/b.html/c/d 	    </td><td> /a/b </td><td> null  </td><td> html </td><td> /c/d       </td></tr>
+<tr><td> /a/b.s1.html/c/d	    </td><td> /a/b </td><td> s1    </td><td> html </td><td> /c/d       </td></tr>
+<tr><td> /a/b.s1.s2.html/c/d	    </td><td> /a/b </td><td> s1.s2 </td><td> html </td><td> /c/d       </td></tr>
+<tr><td> /a/b/c/d.s.txt	    </td><td> /a/b </td><td> null  </td><td> null </td><td> /c/d.s.txt </td></tr>
+<tr><td> /a/b.html/c/d.s.txt	    </td><td> /a/b </td><td> null  </td><td> html </td><td> /c/d.s.txt </td></tr>
+<tr><td> /a/b.s1.html/c/d.s.txt    </td><td> /a/b </td><td> s1    </td><td> html </td><td> /c/d.s.txt </td></tr>
+<tr><td> /a/b.s1.s2.html/c/d.s.txt </td><td> /a/b </td><td> s1.s2 </td><td> html </td><td> /c/d.s.txt </td></tr>
+</table>
+
+{info:title=Automated tests and examples}
+The [SlingRequestPathInfoTest](http://svn.apache.org/repos/asf/sling/trunk/bundles/engine/src/test/java/org/apache/sling/engine/impl/request/SlingRequestPathInfoTest.java)
+ demonstrates and tests this decomposition. Feel free to suggest additional
+tests that help clarify how this works!
+{info}
+
+<a name="SlingAPI-TheSlingHttpServletRequest"></a>
+## The SlingHttpServletRequest
+
+The *org.apache.sling.api.SlingHttpServletRequest* interface defines the
+basic data available from the client request to both action processing and
+response rendering. The *SlingHttpServletRequest* extends the
+*javax.servlet.http.HTTPServletRequest*.
+
+This section describes the data available from the
+*SlingHttpServletRequest*. For a complete and normative description of
+the methods, refer to the Sling API JavaDoc. The following information is
+represented for reference. In the case of differences between the following
+descriptions and the Sling API JavaDoc, the latter takes precedence.
+
+1. *Resource access* - Resources may be accessed from the
+*SlingHttpServletRequest* object through the following methods:
+*getResource()*, *getResourceResolver()*.
+1. *Request URL information* - In addition to the standard
+*HttpServletRequest* information the *SlingHttpServletRequest* provides
+access to the selectors, extension and suffix through the
+*getRequestPathInfo()* method. Note that the Resource path is not
+directly available form the *SlingHttpServletRequest* object. Instead it
+is available through the *Resource.getPath()* method of the Resource
+object retrieved through *SlingHttpServletRequest.getResource()*.
+1. *Request Parameters* - To support user input submitted as
+*multipart/form-data* encoded POST parameters, the Sling API intrduces
+the *RequestParameter* interface allowing file uploads. Request
+parameters represented as *RequestParameter* objects are returned by the
+following methods: *getRequestParameter(String name)*,
+*getRequestParameterMap()*, *getRequestParameters(String name)*.
+1. *Request Dispatching* - In addition to standard Serlvet API request
+dispatching, the Sling API supports dispatching requests to render
+different Resources using *RequestDispatcher* objects returned by the
+methods: *getRequestDispatcher(Resource resource)* and
+{{getRequestDispatcher(Resource resource, RequestDispatcherOptions
+options)}}.
+1. *Miscellaneous* - Finally the ComponentRequest interface provides the
+following methods: *getCookie(String name)*,
+*getRequestProgressTracker()*, *getResponseContentType()*,
+*getResponseContentTypes()*, *getResourceBundle(Locale locale)*,
+*getServiceLocator()*.
+
+The *SlingHttpServletRequest* objects are only valid during the time of
+request processing. Servlets and Scripts must not keep references for later
+use. As such, the *SlingHttpServletRequest* interface and its extensions
+are defined to not be thread safe.
+
+_A note on HTTP Sessions_: The *SlingHttpServletRequest* extends the
+*HttpSerlvetRequest* and thus supports standard HTTP sessions. Be aware,
+though that Sessions are server side sessions and hence violate the
+sessionless principle of REST and therefore should be used with care. It is
+almost always possible to not use sessions.
+
+
+<a name="SlingAPI-TheSlingHttpServletResponse"></a>
+## The SlingHttpServletResponse
+
+The *org.apache.sling.api.SlingHttpServletResponse* interface extends the
+*javax.servet.http.HttpServletResponse* interface and is currently empty.
+It merely exists for symmetry with the *SlingHttpServletRequest*.
+
+
+
+
+<a name="SlingAPI-TheResource"></a>
+## The Resource
+
+The *org.apache.sling.resource.Resource* represents the data addressed by
+the request URL. Resources may also be retrieved through the
+*org.apache.sling.api.resource.ResourceResolver*. Usually this interface
+is not implemented by clients. In certain use cases we call _synthetic
+Resource_ if may be usefull to define a simple object implementing the
+*Resource* interface. The Sling Framework does not care about the
+concrete implementation of the *Resource* interface and rather uses the
+defined methods to access required information. The interface defines the
+following methods:
+
+1. *getResourceType()* - Returns the type of the resource. This resource
+type is used to resolve the Servlet or Script used to handle the request
+for the resource.
+1. *getPath()* - Returns the path derived from the client request URL which
+led to the creation of the Resource instance. See the [#URL_decomposition URL decomposition](#url_decomposition-url-decomposition.html)
+ section above for more information. It is not required, that the Resource
+path be a part of the original client request URL. The request URL may also
+have been mapped to some internal path.
+1. *getResourceMetadata()* - Returns meta data information about the
+resource in a *ResourceMetadata* object.
+1. *adaptTo(Class<AdapterType> type)* - Returns alternative representations
+of the Resource. The concrete supported classes to which the Resource may
+be adapted depends on the implementation. For example a Resource based on a
+JCR Node may support being adapted to the underlying Node, an
+*InputStream*, an *URL* or even to a mapped object through JCR Object
+Content Mapping.
+
+----
+
+
+
+<a name="SlingAPI-TheComponent"></a>
+## The Component
+
+The *org.apache.sling.component.Component* interface defines the API
+implemented to actually handle requests. As such the Component interface is
+comparable to the =javax.servlet.Servlet= interface. Like those other
+interfaces, the Component interface provides methods for life cycle
+management: *init(ComponentContext context)*, *destroy()*.
+
+
+
+<a name="SlingAPI-ProcessingtheRequest"></a>
+### Processing the Request
+
+The Component Framework calls the {{service(ComponentRequest request,
+ComponentResponse response)}} method of the Component to have the component
+process the request optionally processing user input, rendering the
+response and optionally dispatch to other Content/Component tuples to
+provide more response data.
+
+
+
+<a name="SlingAPI-ContentanditsComponent"></a>
+### Content and its Component
+
+The Content object and a Component form a pair, in which the Content object
+takes the passive part of providing data to the Component and the Component
+takes the active part of acting upon the Content object. As a consequence,
+there always exists a link between a given implementation of the Content
+interface and a given implementation of the Component interface.
+
+This link is manifested by the Component identifier available from the
+Content object through the *Content.getComponentId()* method on the one
+hand. On the other hand, the link is manifested by the
+*getContentClassName()* and *createContentInstance()* methods of the
+Component interface.
+
+
+
+<a name="SlingAPI-ComponentLifecylce"></a>
+### Component Lifecylce
+
+When a Component instance is created and added to the Component framework,
+the *init(ComponentContext)* method is called to prepare and initialize
+the Component. If this method terminates abnormally by throwing an
+exception, the Component is not used. The Component Framework
+implementation may try at a later time to recreate the Component, intialize
+it and use it. If the Component Framework tries to recreate the Component a
+new instance of the Component must be created to be initialized and used.
+
+When the Component has successfully been initialized, it may be referred to
+by Content objects. When a client request is to be processed, the Content
+object is resolved and the *service* method on the Component to which the
+Content object refers is called. The *service* method may - and generally
+will - be called simultaneously to handle different requests in different
+threads. As such, implementations of these methods must be thread safe.
+
+When the Component Framework decides to take a Component out of service,
+the *destroy()* method is called to give the Component a chance to
+cleanup any held resources. The destroy method must only be called by the
+Component Framework when no more request processing is using the Component,
+that is no thread may be in the *service* method of a Component to be
+destroyed. Irrespective of whether the destroy method terminated normally
+or abnormally, the Component will not be used again.
+
+The addition and removal of Components is at the discretion of the
+Component Framework. A Component may be loaded at framework start time or
+on demand and my be removed at any time. But only one single Component
+instance with the same Component identifier may be active at the same time
+within a single Component Framework instance.
+
+
+
+<a name="SlingAPI-TheComponentExtension"></a>
+### The ComponentExtension
+
+To enhance the core functionality of Components, each Component may have
+zero, one ore more Component Extensions attached. A Component Extensions is
+a Java object implementing the
+*org.apache.sling.component.ComponentExtension* interface. This interface
+just defines a *getName()* method to identify extensions.
+
+The concrete implementation as well as instantiation and management of
+Component Extensions is left to the Component Framework implementation with
+one restriction though: The extensions must be available to the Component
+at the time the *init(ComponentContext)* method is called may only be
+dropped after the *destroy()* method terminates.
+
+The Component interface defines two methods to access Extensions: The
+*getExtensions()* method returns a *java.util.Enumeration* of all
+ComponentExtension objects attached to the component. If no Component
+Extension are attached to the Component, an empty enumeration is returned.
+The *getExtension(String name)* returns the named Component Extension
+attached to the Component or *null* if no such Component Extension is
+attached to the Component.
+
+Component Frameworks are allowed to share Component Extension instances of
+the same name between different Component instances. Regardless of whether
+Component Extensions are shared or not, they must be thread safe, as any
+Component Extension may be used within the *service* method, which
+themselves may be called concurrently.
+
+
+
+
+<a name="SlingAPI-RequestProcessingFilters"></a>
+## Request Processing Filters
+
+Similar to the Servlet API providing filters for filtering requests and/or
+responses the Component API provides the
+*org.apache.sling.component.ComponentFilter* interface. The filters are
+called by a *ComponentFilterChain* and either handle the request,
+manipulate the request and/or response object and finally forward the
+request and response optionally wrapped to the
+*ComponentFilterChain.doFilter(ComponentRequest, ComponentResponse)*
+method.
+
+Like the *Component*s  filters have a defined lifecycle manifested by
+*init* and *destroy* methods. When the filter enters the system, the
+Component Framework calls the *ComponentFilter.init(ComponentContext)*
+method. Only when this method completes successfully will the filter be put
+into action and be used during request processing. When the filter leaves
+the system, the Component Framework removes the filter from being used in
+filter chains and calls the *ComponentFilter.destroy()* method. This
+method is not expected to throw any exceptions. The filter may be removed
+from the Component Framework at the discretion of the Component Framework
+or because the filter is being unregistered from the Component Framework by
+some means outside this specification.
+
+This specification does not define how *ComponentFilter* objects are
+registered with the Component Framework nor is it specified how the order
+in which the filters are called is defined. Likewise it is outside this
+specification how the filter instances registered with the Component
+Framework are configured.
+
+
+
+<a name="SlingAPI-Sessions"></a>
+## Sessions
+
+
+The *org.apache.sling.component.ComponentSession* interface provides a
+way to identify a user across more than one request and to store transient
+information about that user.
+
+A component can bind an object attribute into a *ComponentSession* by
+name. The *ComponentSession* interface defines two scopes for storing
+objects: *APPLICATION_SCOPE*, *COMPONENT_SCOPE*. All objects stored in
+the session using the *APPLICATION_SCOPE* must be available to all the
+components, servlets and JSPs that belong to the same component application
+and that handle a request identified as being a part of the same session.
+Objects stored in the session using the *COMPONENT_SCOPE* must be
+available to the component during requests for the same content that the
+objects where stored from. Attributes stored in the *COMPONENT_SCOPE* are
+not protected from other web components of the component application. They
+are just conveniently namespaced.
+
+The component session extends the Servlet API *HttpSession*. Therefore
+all *HttpSession* listeners do apply to the component session and
+attributes set in the component session are visible in the *HttpSession*
+and vice versa.
+
+The attribute accessor methods without the _scope_ parameter always refer
+to *COMPONENT_SCOPE* attributes. To access *APPLICATION_SCOPE*
+attributes use the accessors taking an explicit *scope* parameter.
+
+_A final note on Sessions_: Sessions are server side sessions and hence
+violate the sessionless principle of REST and therefore should be used with
+care. It is almost always possible to not use sessions.
+
+
+
+<a name="SlingAPI-DispatchingRequests"></a>
+## Dispatching Requests
+
+To include renderings of child Content objects, a
+*org.apache.sling.component.ComponentRequestDispatcher* object may be
+retrieved from the ComponentContext with which the Component has been
+initialized or from the ComponentRequest provided to the service method.
+Using this dispatcher the reponse of rendering the Content may be included
+by calling the {{ComponentRequestDispatcher.include(ComponentRequest,
+ComponentResponse)}} method.
+
+This method is comparable to the
+*RequestDispatcher.include(ServletRequest, ServletResponse* method of the
+Servlet API but dispatching by the *ComponentRequestDispatcher* does not
+go through the servlet container and stays within the Component Framework.
+
+The *service* method of included Components are called with an instance
+of the *ComponentRequest* interface whose *getContent()* returns the
+Content object for the included Content.
+
+When a Component is included by another component the following request
+attributes are set:
+
+<table>
+<tr><th> *Request Attributes* </th><th> *Type* </th><th> *Description* </th></tr>
+<tr><td> *org.apache.sling.component.request.content* </td><td> String </td><td> The *Content*
+instance to which the client URL resolved. This attribute is set when
+included Components are being rendered and it is not set for the Component
+directly addressed by the client request. </td></tr>
+<tr><td> *org.apache.sling.component.request.component* </td><td> String </td><td> The
+*Component* instance for the *Content* object to which the client URL
+resolved. This attribute is set when included Components are being rendered
+and it is not set for the Component directly addressed by the client
+request. </td></tr>
+</table>
+
+
+<a name="SlingAPI-ErrorHandling"></a>
+### Error Handling
+
+While processing requests, the *service* methods called may have
+problems. Components have multiple options of reporting issues during
+processing to the client:
+
+* Set the status of the HTTP response calling the
+*ComponentResponse.setStatus* method
+* Send an error page calling the *ComponentResponse.sendError* method
+* Throw an exception
+
+
+If such an exception is thrown, the Component Framework must act upon the
+exception in one of the following ways:
+
+* If the request is processed through Servlet API request inclusion, the
+exception must be given back to the servlet container. A
+*ComponentException* is just forwarded as a *ServletException*. This is
+a requirement of the Servlet API specification which states for included
+requests:
+
+{quote}
+  
+  
+{quote}
+
+* Otherwise, the Component Framework may handle the error itself in a
+manner similar to the error handling approach defined the Servlet API
+specification (Section SRV 9.9 Error Handling of the Java Servlet
+Specification 2.4). Specifically the request attributes defined by the
+Servlet API specification must be set for the error handler:
+
+<table>
+<tr><th> *Request Attributes* </th><th> *Type* </th><th> *Description* </th></tr>
+<tr><td> *javax.servlet.error.status_code* </td><td> *java.lang.Integer* </td><td> The status
+code of the response. In the case of an exception thrown from the
+*service*, the code is defined by the Component Framework. </td></tr>
+<tr><td> *javax.servlet.error.exception_type* </td><td> *java.lang.Class* </td><td> The fully
+qualified name of the exception class thrown. This attribute does not
+exist, if error handling does not result from an exception. This attribute
+is maintained for backwards compatibility according to the Servlet API
+Specification. </td></tr>
+<tr><td> *javax.servlet.error.message* </td><td> *java.lang.String* </td><td> The message of
+the exception thrown. This attribute does not exist, if error handling does
+not result from an exception. This attribute is maintained for backwards
+compatibility according to the Servlet API Specification. </td></tr>
+<tr><td> *javax.servlet.error.exception* </td><td> *java.lang.Throwable* </td><td> The
+exception thrown. This attribute does not exist, if error handling does not
+result from an exception. </td></tr>
+<tr><td> *javax.servlet.error.request_uri* </td><td> *java.lang.String* </td><td> The request
+URL whose processing resulted in the error. </td></tr>
+<tr><td> *javax.servlet.error.servlet_name* </td><td> *java.lang.String* </td><td> The name of
+the servlet which yielded the error. The servlet name will generally not
+have any significance inside the Component Framework. </td></tr>
+<tr><td> *org.apache.sling.component.error.componentId* </td><td> *java.lang.String* </td><td>
+The identifier of the Component whose *service* method has caused the
+error. This attribute does not exist, if the Component Framework itself
+caused the error processing. </td></tr>
+* If the Component Framework decides to not handle the error itself, the
+exception must be forwarded to the servlet container as a
+*ComponentException* wrapping the original exception as its root cause.
+</table>
+
+This specification does not define, how error handlers are configured and
+used if the Component Framework provides error handling support. Likewise
+the Component Framework may or may not implement support to handle calls to
+the *ComponentResponse.sendError* method. The Component Framework may
+also use its own error handling also for errors resulting from request
+processing failures, for example if authentication is required or if the
+request URL cannot be resolved to a Content object.

Added: sling/site/trunk/content/sling-testing-tools.mdtext
URL: http://svn.apache.org/viewvc/sling/site/trunk/content/sling-testing-tools.mdtext?rev=1328899&view=auto
==============================================================================
--- sling/site/trunk/content/sling-testing-tools.mdtext (added)
+++ sling/site/trunk/content/sling-testing-tools.mdtext Sun Apr 22 16:52:13 2012
@@ -0,0 +1,202 @@
+Title: Sling Testing Tools
+<a name="SlingTestingTools-SlingTestingTools"></a>
+# Sling Testing Tools
+Sling provides a number of testing tools to support the following use
+cases:
+* Run JUnit tests contributed by OSGi bundles in an OSGi system. This does
+not require Sling and should work in other OSGi  environments.
+* Run scriptable tests in a Sling instance, using any supported scripting
+language.
+* Run integration tests via HTTP against a Sling instance that is started
+during the Maven build cycle, or independently.
+
+This page describes those tools, and points to the bundles that implement
+them.
+
+The [testing/samples/integration-tests](http://svn.apache.org/repos/asf/sling/trunk/testing/samples/integration-tests)
+ module demonstrates these tools, and is also meant as a sample project to
+show how to run integration tests for Sling-based applications.
+
+The main Sling integration tests at [launchpad/integration-tests](https://svn.apache.org/repos/asf/sling/trunk/launchpad/integration-tests)
+ were created before this testing framework, and do not use it yet (as of
+March 2011). The new testing tools are simpler to use, but the "old" tests
+(all 400 of them as I write this) fulfill their validation role for testing
+Sling itself, there's no real need to modify them to use the new tools.
+
+<a name="SlingTestingTools-Server-sideJUnittestscontributedbybundles"></a>
+# Server-side JUnit tests contributed by bundles
+The services provided by the [org.apache.sling.junit.core](http://svn.apache.org/repos/asf/sling/trunk/testing/junit/core)
+ bundle allow bundles to register JUnit tests, which are executed
+server-side by the JUnitServlet registered by default at
+*/system/sling/junit*. This bundle is not dependent on Sling, it should
+work in other OSGi environments.
+
+{warning:title=JUnit servlet security}
+Note that the JUnitServlet does not require authentication, so it would
+allow any client to run tests. The servlet can be disabled by configuration
+if needed, but in general the */system* path should not be accessible to
+website visitors anyway.
+{warning}
+
+{note:title=SlingJUnitServlet}
+For tighter integration with Sling, the alternate *SlingJUnitServlet* is
+registered with the *sling/junit/testing* resource type and *.junit*
+selector, if the bundle is running in a Sling system. Using this servlet
+instead of the plain JUnitServlet also allows Sling authentication to be
+used for running the tests, and the standard Sling request processing is
+used, including servlet filters for example.
+{note}
+
+To try the JUnitServlet interactively, install the [org.apache.sling.testing.samples.sampletests](http://svn.apache.org/repos/asf/sling/trunk/testing/samples/sample-tests)
+ bundle.
+
+This bundle contains a number of test classes, which are registered with
+the *org.apache.sling.junit.core* services by way of the
+*Sling-Test-Regexp=.*Test* bundle header, defined in the bundle's
+*pom.xml*. The JUnit core services use this regular expression to select
+which classes of the test bundle should be executed as JUnit tests.
+
+To list the available tests, open http://localhost:8080/system/sling/junit/
+. The servlet shows available tests, and allows you to execute them via a
+POST request.
+
+Adding a path allows you to select a specific subset of tests, as in
+http://localhost:8080/system/sling/junit/org.apache.sling.junit.remote.html
+- the example integration tests described below use this to selectively
+execute server-side tests. The JUnitServlet provides various output
+formats, including in particular JSON, see
+http://localhost:8080/system/sling/junit/.json for example.
+
+To supply tests from your own bundles, simply export the tests classes and
+add the *Sling-Test-Regexp* header to the bundle so that the Sling JUnit
+core services register them as tests.
+
+<a name="SlingTestingTools-InjectionofOSGiservices"></a>
+### Injection of OSGi services
+The *@TestReference* annotation is used to inject OSGi services in tests
+that are executed server side.The *BundleContext* can also be injected in
+this way, see the [OsgiAwareTest](http://svn.apache.org/repos/asf/sling/trunk/testing/samples/sample-tests/src/main/java/org/apache/sling/testing/samples/sampletests/OsgiAwareTest.java)
+ for an example.
+
+<a name="SlingTestingTools-Curlexamples"></a>
+## Curl examples
+Here's an example executing a few tests using curl:
+
+<DIV class="code panel" style="border-style: solid;border-width: 1px;"><DIV class="codeHeader panelHeader" style="border-bottom-width: 1px;border-bottom-style: solid;"><B>Running tests with curl</B></DIV><DIV class="codeContent panelContent">
+    $ curl -X POST
+http://localhost:8080/system/sling/junit/org.apache.sling.testing.samples.sampletests.JUnit.json
+    [{
+        "INFO_TYPE": "test",
+        "description":
+"testPasses(org.apache.sling.testing.samples.sampletests.JUnit3Test)"
+      },{
+        "INFO_TYPE": "test",
+        "description":
+"testPasses(org.apache.sling.testing.samples.sampletests.JUnit4Test)"
+      },{
+        "INFO_TYPE": "test",
+        "description":
+"testRequiresBefore(org.apache.sling.testing.samples.sampletests.JUnit4Test)"
+      }
+    ]
+
+
+And another example with a test that fails:
+<DIV class="code panel" style="border-style: solid;border-width: 1px;"><DIV class="codeHeader panelHeader" style="border-bottom-width: 1px;border-bottom-style: solid;"><B>Failing tests with curl</B></DIV><DIV class="codeContent panelContent">
+    $ curl -X POST
+http://localhost:8080/system/sling/junit/org.apache.sling.testing.samples.failingtests.JUnit4FailingTest.json
+    [continuous integration|SLINGxSITE:Project Information]
+
+
+<a name="SlingTestingTools-Scriptableserver-sidetests"></a>
+# Scriptable server-side tests
+If the [org.apache.sling.junit.scriptable](http://svn.apache.org/repos/asf/sling/trunk/testing/junit/scriptable)
+ bundle is active in a Sling system, (in addition to the
+*org.apache.sling.junit.core* bundle), scriptable tests can be executed
+by the *JUnitServlet* according to the following rules:
+
+* A node that has the *sling:Test* mixin is a scriptable test node.
+* For security reasons, scriptable test nodes are only executed as tests if
+they are found under */libs* or */apps*, or more precisely under a path
+that's part of Sling's *ResourceResolver* search path.
+* To execute a test, the scriptable tests provider makes an HTTP requests
+to the test node's path, with a *.test.txt* selector and extension, and
+expects the output to contain only the string *TEST_PASSED*. Empty lines
+and comment lines starting with a hash sign (#) are ignored in the output,
+and other lines are reported as failures.
+
+The [ScriptableTestsTest](http://svn.apache.org/repos/asf/sling/trunk/testing/samples/integration-tests/src/test/java/org/apache/sling/testing/samples/integrationtests/serverside/scriptable/ScriptableTestsTest.java)
+ class, from the integration test samples module described below, sets up
+such a test node and its accompanying script, and calls the JUnitServlet to
+execute the test. It can be used as a detailed example of how this works.
+
+<a name="SlingTestingTools-Integrationtestsexample"></a>
+# Integration tests example
+The [testing/samples/integration-tests](http://svn.apache.org/repos/asf/sling/trunk/testing/samples/integration-tests)
+ module runs some simple integration tests against a Sling Launchpad
+instance that's setup from scratch before running the tests.
+
+This module's pom and Java code can be used as examples to setup your own
+integration testing modules for Sling-based apps - or for any other
+runnable jar that provides an http service.
+
+Besides serving as examples, some of the tests in this module are used to
+validate the testing tools. They run as part of the full Sling [continuous integration](project-information.html)
+ build, so they're guaranteed to be correct examples if that build is
+successful.
+
+The sample uses the [testing/tools](http://svn.apache.org/repos/asf/sling/trunk/testing/tools)
+ to make the test code simpler. See the [OsgiConsoleTest|https://svn.apache.org/repos/asf/sling/trunk/testing/samples/integration-tests/src/test/java/org/apache/sling/testing/samples/integrationtests/http/OsgiConsoleTest.java]
+ class for an example of a test that's very readable and requires no test
+setup or boilerplate code.
+
+The following steps are executed in the *integration-test* phase of this
+module's Maven	build:
+1. A random port number for the Sling server is selected by the Maven build
+helper plugin, unless explicitely set (see pom.xml for such options).
+1. Additional bundles, defined in the module's pom, are downloaded from the
+Maven repository in the *target/sling/additional-bundles* folder.
+1. The first test that inherits from the [SlingTestBase](https://svn.apache.org/repos/asf/sling/trunk/testing/tools/src/main/java/org/apache/sling/testing/tools/sling/SlingTestBase.java)
+ class causes the Sling runnable jar (defined as a dependency in the
+module's pom) to be started. 
+1. # The *SlingTestBase* class waits for the Sling server to be ready,
+based on URLs and expected responses defined in the pom.
+1. # The *SlingTestBase* class installs and starts the bundles found in the
+*target/sling/additional-bundles* folder.
+1. The test can now either test Sling directly via its http interface, or
+use the JUnitServlet to execute server-side tests contributed by bundles or
+scripts, as described above.
+1. The Sling runnable jar is stopped when the test VM exits.
+1. The test results are reported via the usual Maven mechanisms.
+
+If *-DkeepJarRunning* is used on the Maven command line, the Sling
+runnable jar does not exit, to allow for running individual tests against
+this instance, for example when debugging the tests or the server code. See
+the pom for details.
+
+<a name="SlingTestingTools-Remotetestexecution"></a>
+# Remote test execution
+The testing tools support two types of remote test execution.
+
+<a name="SlingTestingTools-SlingRemoteTestRunner"></a>
+## SlingRemoteTestRunner
+The [SlingRemoteTestRunner](http://svn.apache.org/repos/asf/sling/trunk/testing/junit/remote/src/main/java/org/apache/sling/junit/remote/testrunner/SlingRemoteTestRunner.java)
+ is used to run tests using the *JUnitServlet* described above. In this
+case, the client-side JUnit test only defines which tests to run and some
+optional assertions. Checking the number of tests executed, for example,
+can be useful to make sure all test bundles have been activated as
+expected, to avoid ignoring missing test bundles.
+
+See the [ServerSideSampleTest](https://svn.apache.org/repos/asf/sling/trunk/testing/samples/integration-tests/src/test/java/org/apache/sling/testing/samples/integrationtests/serverside/ServerSideSampleTest.java)
+ class for an example.
+
+<a name="SlingTestingTools-SlingRemoteExecutionRule"></a>
+## SlingRemoteExecutionRule
+The [SlingRemoteExecutionRule](http://svn.apache.org/repos/asf/sling/trunk/testing/junit/remote/src/main/java/org/apache/sling/junit/remote/ide/SlingRemoteExecutionRule.java)
+ is a JUnit Rule that allows tests to be executed remotely in a Sling
+instance from an IDE, assuming the test is available on both sides.
+
+The [ExampleRemoteTest](https://svn.apache.org/repos/asf/sling/trunk/testing/junit/remote/src/main/java/org/apache/sling/junit/remote/exported/ExampleRemoteTest.java)
+ class demonstrates this. To run it from your IDE, set the
+*sling.remote.test.url* in the IDE to the URL of the JUnitServlet, like
+http://localhost:8080/system/sling/junit for example.

Added: sling/site/trunk/content/sling.mdtext
URL: http://svn.apache.org/viewvc/sling/site/trunk/content/sling.mdtext?rev=1328899&view=auto
==============================================================================
--- sling/site/trunk/content/sling.mdtext (added)
+++ sling/site/trunk/content/sling.mdtext Sun Apr 22 16:52:13 2012
@@ -0,0 +1,418 @@
+Title: Sling
+<a name="Sling-MavenSlingPlugin"></a>
+# Maven Sling Plugin
+
+The Maven Sling Plugin provides a number of goals which may be of help
+while developping bundles for Sling. To run the plugin you need at least
+Maven 2.x and JDK 1.5 or higher. Maven Sling Plugin provides the following
+goals:
+  
+  
+<table>
+<tr><td> [sling:deploy](#deploy.html)
+ </td><td> Deploy a OSGi-bundle into a running Sling instance. </td></tr>
+<tr><td> [sling:deploy-file](#deploy-file.html)
+ </td><td> Deploy a OSGi-bundle into a running Sling instance without requiring a
+project descriptor file. </td></tr>
+  
+  
+<tr><td> [sling:install-file](#install-file.html)
+ </td><td> Install a OSGi-bundle into a running Sling instance without requiring a
+project descriptor file. </td></tr>
+  
+  
+  
+  
+</table>
+
+<a name="Sling-Usage"></a>
+## Usage
+
+You should specify the version in your project's plugin configuration:
+
+    <project>
+      ...
+      <build>
+        <!-- To define the plugin version in your parent POM -->
+        <pluginManagement>
+          <plugins>
+    	<plugin>
+    	  <groupId>org.apache.sling</groupId>
+    	  <artifactId>maven-sling-plugin</artifactId>
+    	  <version>2.0.5-SNAPSHOT</version>
+    	</plugin>
+    	...
+          </plugins>
+        </pluginManagement>
+        <!-- To use the plugin goals in your POM or parent POM -->
+        <plugins>
+          <plugin>
+    	<groupId>org.apache.sling</groupId>
+    	<artifactId>maven-sling-plugin</artifactId>
+    	<version>2.0.5-SNAPSHOT</version>
+          </plugin>
+          ...
+        </plugins>
+      </build>
+      ...
+    </project>
+
+For more information, see ["Guide to Configuring Plug-ins"](http://maven.apache.org/guides/mini/guide-configuring-plugins.html)
+
+{anchor:deploy}
+
+<a name="Sling-The*deploy*goal"></a>
+## The *deploy* goal
+
+The *deploy* goal uploads a bundle to a Sling OSGi Bundle Repository
+server implemented by the _sling-obr_ bundle, which may be located on a
+remote system. The plugin places an HTTP *POST* request to the server
+sending the bundle file.&nbsp;
+
+<a name="Sling-Use"></a>
+### Use
+
+To use the *deploy* goal of the Maven Sling Plugin define the following
+elements in the *<plugins>* section of the POM:
+
+    <?xml version="1.0" encoding="ISO-8859-1"?>
+    <project>
+      ....
+      <build>
+        ....
+        <plugins>
+          ....
+          <plugin>
+    	<groupId>org.apache.sling</groupId>
+    	<artifactId>maven-sling-plugin</artifactId>
+    	<executions>
+    	  <execution>
+    	    <id>deploy-bundle</id>
+    	    <goals>
+    	      <goal>deploy</goal>
+    	    </goals>
+    	  </execution>
+    	</executions>
+          </plugin>
+          ....
+        <plugins>
+        ....
+      <build>
+      ....
+    <project>
+
+
+<a name="Sling-Configuration"></a>
+### Configuration
+
+The *deploy* goal may be configured in the *<configuration>* element
+using the following properties:
+<table>
+<tr><th> Parameter </th><th> Default Value </th><th> System Property Overwrite </th><th> Description
+</th></tr>
+<tr><td> *skip* </td><td> *false* </td><td> *sling.deploy.skip* </td><td> Whether to skip this step
+even though it has been configured in the project to be executed. The main
+use of this setting is preventing deployment of the bundle to a Sling OSGi
+Bundle Repository server if it is known that there is none or if such an
+upload is not required. </td></tr>
+<tr><td> *buildDirectory* </td><td> *$\{project.build.directory*} </td><td> \- </td><td> The path of
+the file to be installed </td></tr>
+<tr><td> *jarName* </td><td> *$\{project.build.finalName}.jar* </td><td> \- </td><td> The name of the
+file to be installed </td></tr>
+<tr><td> *obr* </td><td> \- </td><td> *obr* </td><td> The URL of the running Sling instance to which
+the bundle is installed. Note that this parameter is required and has no
+defualt value. It must always be specified in the configuration section or
+on the command line. </td></tr>
+{anchor:deploy-file}
+</table>
+
+<a name="Sling-The*deploy-file*goal"></a>
+## The *deploy-file* goal
+
+The *deploy-file* goal is equivalent to the *deploy* goal except, that
+the *deploy-file* does not require a project descriptor file while the
+*deploy* goal does. In other words the *deploy-file* goal may used to
+upload any bundle file available to a Sling OBR server instance.
+
+<a name="Sling-Use"></a>
+### Use
+
+The *deploy-file* goal may only be used from the command line by
+explicitly calling it as in:
+
+    $ mvn org.apache.sling:maven-sling-plugin:deploy-file -Dsling.file=<file>
+-Dobr=<url>
+
+Specifying the bundle file to upload with the *sling.file* property is
+required.
+
+<a name="Sling-Configuration"></a>
+### Configuration
+
+The *deploy-file* supports similar configuration parameters as the
+*deploy* goal with the exception of the *skip* parameter which makes no
+sense. In addition, all parameters must be specified on the command line by
+setting system properties. The *bundleFileName* parameter specified as
+the *sling.file* system property as well as the *obr* URL are required
+by the *deploy-file* goal.
+<table>
+<tr><th> Parameter </th><th> Default Value </th><th> System Property Overwrite </th><th> Description
+</th></tr>
+<tr><td> *bundleFileName* </td><td>
+*$\{project.build.directory}/$\{project.build.finalName}.jar* </td><td>
+*sling.file* </td><td> The path and name of the file to be installed </td></tr>
+<tr><td> *obr* </td><td> \- </td><td> *obr* </td><td> The URL of the running Sling instance to which
+the bundle is installed. Note that this parameter is required and has no
+defualt value. It must always be specified in the configuration section or
+on the command line. </td></tr>
+Example: To deploy the bundle file *someBundle.jar* to the OBR running at {{[http://obr.sample.org](http://obr.sample.org)
+}} you might use the goal as follows:
+
+    $ mvn org.apache.sling:maven-sling-plugin:deploy-file
+-Dsling.file=someBundle.jar -Dobr=http://obr.sample.org
+
+{anchor:install}
+
+<a name="Sling-The*install*goal"></a>
+## The *install* goal
+
+The *install* goal uploads a bundle to a running sling instance, which
+may be located on a remote system. The plugin places an HTTP *POST*
+request to the sling instance sending the bundle file together with flags
+indicating whether to start the bundle and what start level to assign the
+bundle. It's also possible to HTTP *PUT* instead of *POST* for WebDAV.
+
+<a name="Sling-Use"></a>
+### Use
+
+To use the *install* goal of the Maven Sling Plugin define the following
+elements in the *<plugins>* section of the POM:
+
+    <?xml version="1.0" encoding="ISO-8859-1"?>
+    <project>
+      ....
+      <build>
+        ....
+        <plugins>
+          ....
+          <plugin>
+    	<groupId>org.apache.sling</groupId>
+    	<artifactId>maven-sling-plugin</artifactId>
+    	<executions>
+    	  <execution>
+    	    <id>install-bundle</id>
+    	    <goals>
+    	      <goal>install</goal>
+    	    </goals>
+    	  </execution>
+    	</executions>
+          </plugin>
+          ....
+        <plugins>
+        ....
+      <build>
+      ....
+    <project>
+
+
+<a name="Sling-Configuration"></a>
+### Configuration
+
+The *install* goal may be configured in the *<configuration>* element
+using the following properties:
+<table>
+<tr><th> Parameter </th><th> Default Value </th><th> System Property Overwrite </th><th> Description
+</th></tr>
+<tr><td> *skip* </td><td> *false* </td><td> *sling.install.skip* </td><td> Whether to skip this step
+even though it has been configured in the project to be executed. The main
+use of this setting is preventing installation of the bundle to a running
+Sling installation if it is known that there is none or if such an upload
+is not required, for example when building the bundle in an automated build
+system such as Confluence. </td></tr>
+<tr><td> *bundleFileName* </td><td>
+*$\{project.build.directory}/$\{project.build.finalName}.jar* </td><td>
+*sling.file* </td><td> The path and name of the file to be installed </td></tr>
+<tr><td> *bundleStart* </td><td> *true* </td><td> *sling.bundle.start* </td><td> Whether to start
+the bundle after installing it. If the bundle is just updated, this
+parameter is ignored even if the bundle is currently stopped </td></tr>
+<tr><td> *bundleStartLevel* </td><td> *20* </td><td> *sling.bundle.startlevel* </td><td> The start
+level to set on the installed bundle. If the bundle is already installed
+and therefore is only updated this parameter is ignored. The parameter is
+also ignored if the running Sling instance has no StartLevel service (which
+is unusual actually) </td></tr>
+<tr><td> *slingUrl* </td><td> *http{*}*://localhost:8080/sling* </td><td> *sling.url* </td><td>
+The URL of the running Sling instance to which the bundle is installed </td></tr>
+<tr><td> *user* </td><td> *admin* </td><td> *sling.user* </td><td> The name of the user to
+authenticate as with the running Sling instance given by the *slingUrl*
+parameter </td></tr>
+<tr><td> *password* </td><td> *admin* </td><td> *sling.password* </td><td> The password of the user
+to authenticate as with the running Sling instance given by the
+*slingUrl* parameter </td></tr>
+  
+  
+<tr><td> *usePut* </td><td> *false* </td><td> *sling.usePut* </td><td> If a simple HTTP PUT should
+be used instead of the standard POST to the  felix console. In the
+uninstall goal, a HTTP DELETE will be  used. </td></tr>
+<tr><td> *refreshPackages* </td><td> *true* </td><td> *sling.refreshPackages* </td><td> Whether to refresh the packages after installing the uploaded bundle. If this property is set to *true*, the {{PackageAdmin.refreshPackages(Bundle\[\](\.html)
+)}} method is called after installing or updating the bundle. </td></tr>
+{anchor:install-file}
+</table>
+
+<a name="Sling-The*install-file*goal"></a>
+## The *install-file* goal
+
+The *install-file* goal is equivalent to the *install* goal except,
+that the *install-file* does not require a project descriptor file while
+the *install* goal does. In other words the *install-file* goal may
+used to upload any bundle file available to a running Sling instance.
+
+<a name="Sling-Use"></a>
+### Use
+
+The *install-file* goal may only be used from the command line by
+explicitly calling it as in:
+
+    $ mvn org.apache.sling:maven-sling-plugin:install-file -Dsling.file=<file>
+
+Specifying the bundle file to upload with the *sling.file* property is
+required.
+
+<a name="Sling-Configuration"></a>
+### Configuration
+
+The *install-file* supports the same configuration parameters as the
+*install* goal with the exception of the *skip* parameter which makes
+no sense. In addition, all parameters must be specified on the command line
+by setting system properties. The *bundleFileName* parameter specified as
+the *sling.file* system property is required by the *install-file*
+goal.
+
+For a description of the parameters see the configuration section of the [*install* goal](#install.html)
+ above.
+
+Example: To upload the bundle file *someBundle.jar* you might use the
+goal as follows:
+
+    $ mvn org.apache.sling:maven-sling-plugin:install-file
+-Dsling.file=someBundle.jar
+
+{anchor:uninstall}
+
+<a name="Sling-The*uninstall*goal"></a>
+## The *uninstall* goal
+
+The *uninstall* goal uninstalls a bundle from a running sling instance,
+which may be located on a remote system. The plugin uninstalles a bundle
+via a HTTP *POST{*}request. It's also possible to use HTTP *DELETE*
+instead of *POST* for WebDAV.
+
+<a name="Sling-Use"></a>
+### Use
+
+To use the *uninstall* goal of the Maven Sling Plugin define the
+following elements in the *<plugins>* section of the POM:
+
+    <?xml version="1.0" encoding="ISO-8859-1"?>
+    <project>
+      ....
+      <build>
+        ....
+        <plugins>
+          ....
+          <plugin>
+    	<groupId>org.apache.sling</groupId>
+    	<artifactId>maven-sling-plugin</artifactId>
+    	<executions>
+    	  <execution>
+    	    <id>uninstall-bundle</id>
+    	    <goals>
+    	      <goal>uninstall</goal>
+    	    </goals>
+    	  </execution>
+    	</executions>
+          </plugin>
+          ....
+        <plugins>
+        ....
+      <build>
+      ....
+    <project>
+
+
+<a name="Sling-Configuration"></a>
+### Configuration
+
+The *uninstall* goal may be configured in the *<configuration>* element
+using the following properties:
+<table>
+<tr><th> Parameter </th><th> Default Value </th><th> System Property Overwrite </th><th> Description
+</th></tr>
+<tr><td> *bundleFileName* </td><td>
+*$\{project.build.directory}/$\{project.build.finalName}.jar* </td><td>
+*sling.file* </td><td> The path and name of the file to be uninstalled </td></tr>
+<tr><td> *slingUrl* </td><td> *http{*}*://localhost:8080/sling* </td><td> *sling.url* </td><td>
+The URL of the running Sling instance to which the bundle should be
+uninstalled </td></tr>
+<tr><td> *user* </td><td> *admin* </td><td> *sling.user* </td><td> The name of the user to
+authenticate as with the running Sling instance given by the *slingUrl*
+parameter </td></tr>
+<tr><td> *password* </td><td> *admin* </td><td> *sling.password* </td><td> The password of the user
+to authenticate as with the running Sling instance given by the
+*slingUrl* parameter </td></tr>
+<tr><td> *usePut* </td><td> *false* </td><td> *sling.usePut* </td><td> In the uninstall goal, a HTTP
+DELETE will be used. </td></tr>
+{anchor:validate}
+</table>
+
+<a name="Sling-The*validate*goal"></a>
+## The *validate* goal
+
+The *validate* goal checks the JSON code of a bundle.
+
+<a name="Sling-Use"></a>
+### Use
+
+To use the *validate* goal of the Maven Sling Plugin define the following
+elements in the *<plugins>* section of the POM:
+
+    <?xml version="1.0" encoding="ISO-8859-1"?>
+    <project>
+      ....
+      <build>
+        ....
+        <plugins>
+          ....
+          <plugin>
+    	<groupId>org.apache.sling</groupId>
+    	<artifactId>maven-sling-plugin</artifactId>
+    	<executions>
+    	  <execution>
+    	    <id>validate-bundle</id>
+    	    <goals>
+    	      <goal>validate</goal>
+    	    </goals>
+    	  </execution>
+    	</executions>
+          </plugin>
+          ....
+        <plugins>
+        ....
+      <build>
+      ....
+    <project>
+
+
+<a name="Sling-Configuration"></a>
+### Configuration
+
+The *validate* goal may be configured in the *<configuration>* element
+using the following properties:
+<table>
+<tr><th> Parameter </th><th> Default Value </th><th> System Property Overwrite </th><th> Description
+</th></tr>
+<tr><td> *skip* </td><td> *false* </td><td> *sling.validation.skip* </td><td> Whether to skip the
+validation </td></tr>
+<tr><td> *skipJson* </td><td> *false* </td><td> *sling.validation.skipJson* </td><td> Whether to
+skip the JSON validation. At the time, there's no difference between
+*skip* and *skipJson* because only JSON files will be validated by now.
+</td></tr>

Added: sling/site/trunk/content/the-sling-engine.mdtext
URL: http://svn.apache.org/viewvc/sling/site/trunk/content/the-sling-engine.mdtext?rev=1328899&view=auto
==============================================================================
--- sling/site/trunk/content/the-sling-engine.mdtext (added)
+++ sling/site/trunk/content/the-sling-engine.mdtext Sun Apr 22 16:52:13 2012
@@ -0,0 +1,32 @@
+Title: The Sling Engine
+<a name="TheSlingEngine-TheSlingEngine"></a>
+# The Sling Engine
+
+<a name="TheSlingEngine-General"></a>
+## General
+* [Architecture](architecture.html)
+* [Authentication](authentication.html)
+
+<a name="TheSlingEngine-RequestHandling"></a>
+## Request Handling
+
+* [Dispatching Requests](dispatching-requests.html)
+* [URL decomposition](url-decomposition.html)
+* [Request Listeners](request-listeners.html)
+* [Filters](filters.html)
+* [Servlets and Scripts](servlets.html)
+* [Errorhandling](errorhandling.html)
+* [Request Parameters](request-parameters.html)
+
+<a name="TheSlingEngine-Resources"></a>
+## Resources
+
+* [Resources](resources.html)
+* [Wrap or Decorate Resources](wrap-or-decorate-resources.html)
+* [Mappings for Resource Resolution](mappings-for-resource-resolution.html)
+
+<a name="TheSlingEngine-Misc"></a>
+## Misc
+
+* [Adapters](adapters.html)
+* [Eventing and Jobs](eventing-and-jobs.html)



Mime
View raw message