This is an old version of the Sling website, see the site conversion page for more info.
Apache Sling Website > Apache Sling > Documentation > Tutorials & How-Tos > Rewriting the Output Through Pipelines

Apache Sling Rewriter

The Apache Sling rewriter is a module for rewriting the output. The output from Sling can be rewritten by a SAX based pipeline or a single component (called a Processor).

SAX Pipelines

The rewriter allows to configure a pipeline for post processing of the generated response.

The pipeline starts with a generator. The generator gets the output from Sling. It's the task of the generator to generate SAX events (XML) and stream these into the pipeline. A transformer is a component in the middle of the pipeline, a pipeline can have zero to n transformers. The transformer receives SAX events from the previous component in the pipeline and sends SAX events to the next component in the pipeline. A transformer can remove events, change events, add events or just pass on the events. The pipeline ends with a serializer collecting all SAX events and writing the output to a provided output stream.

Sling contains a default pipeline which is executed for all html responses: it starts with an html generator, parsing the html output and sending events into the pipeline. A html serializer collects all events and serializes the output.

The pipelines can be configured in the repository as a child node of /apps/APPNAME/config/rewriter (or /libs/APPNAME/config/rewriterg). (In fact the configured search paths of the resource resolver are observed.) Each node can have the following properties:

If a component needs a configuration, the configuration is stored in a child node which name is COMPONENTTYPE-NAME, e.g. to configure the html generator (named html-generator), the node should have the name generator-html-generator.

Configuring the HTML Generator

By default the used html generator only generates events for some of the html tags. If you want to change this, create a pipeline config like outlined above for the pipeline and configure the html generator by adding the generator-html-generator node with a multi value string property named includeTags. The values define the tags, the parser uses.

Default Pipeline

The default pipeline is configured for the text/html mime type and consists of the html-generator as generator, and the html-serializer for generating the final response.
As the html generated by Sling is not required to be valid XHTML, the html parser is only sending partial SAX events into the pipeline, therefore modifications of the complete page are not possible with this approach. For complete page modifications, the Sling scripts need to generate XHTML and an according parser needs to be used. It is also possible to integrate an HTML parser which converts the HTML to XHTML.

Implementing Pipeline Components

Each pipeline component type has a corresponding Java interface (Generator, Transformer, and Serializer) together with a factory interface (GeneratorFactory, TransformerFactory, and SerializerFactory). When implementing such a component, both interfaces need to be implemented. The factory has only one method which creates a new instance of that type for the current request. The factory has to be registered as a service. For example if you're using the Maven SCR plugin, it looks like this:

@scr.component metatype="no" 
@scr.service interface="TransformerFactory"
@scr.property value="pipeline.type" value="validator"

The factory needs to implement the according interface and should be registered as a service for this factory. Each factory gets a unique name through the pipeline.type property. The pipeline configuration in the repository just references this unique name (like validator).

Extending the Pipeline

With the possibilities from above, it is possible to define new pipelines and add custom components to the pipeline. However, in some cases it is required to just add a custom transformer to the existing pipeline. Therefore the rewriting can be configured with pre and post transformers that are simply added to each configured pipeline. This allows a more flexible way of customizing the pipeline without changing/adding a configuration in the repository.

The approach here is nearly the same. A transformer factory needs to be implemented, but instead of giving this factory a unique name, this factory is marked as a global factory:

@scr.component metatype="no"
@scr.service interface="TransformerFactory"
@scr.property name="pipeline.mode" value="global"
@scr.property name="service.ranking" value="RANKING" type="Integer"

RANKING is an integer value (don't forget the type attribute otherwise the ranking is interpreted as zero!) specifying where to add the transformer in the pipeline. If the value is less than zero the transformer is added at the beginning of the pipeline right after the generator. If the ranking is equal or higher as zero, the transformer is added at the end of the pipeline before the serializer.

The TransformerFactory interface has just one method which returns a new transformer instance. If you plan to use other services in your transformer you might declare the references on the factory and pass in the instances into the newly created transformer.

Implementing a Processor

A processor must conform to the Java interface org.apache.sling.rewriter.Processor. It gets initializd (method init) with the ProcessingContext. This context contains all necessary information for the current request (especially the output writer to write the rewritten content to).
The getWriter method should return a writer where the output is written to. When the output is written or an error occured finished is called.

Like the pipeline components a processor is generated by a factory which has to be registered as a service factory, like this:

@scr.component metatype="no" 
@scr.service interface="ProcessorFactory"
@scr.property value="pipeline.type" value="uniqueName"

Configuring a Processor

The processors can be configured in the repository as a child node of /apps/APPNAME/config/rewriter (or libs or any configured search path). Each node can have the following properties:

Last modified by cziegeler@apache.org on 2009-06-09 03:15:45.0