You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by bd...@apache.org on 2016/04/04 13:35:14 UTC

svn commit: r1737658 - in /sling/trunk/contrib: ./ extensions/sling-dynamic-include/ extensions/sling-dynamic-include/src/ extensions/sling-dynamic-include/src/main/ extensions/sling-dynamic-include/src/main/doc/ extensions/sling-dynamic-include/src/ma...

Author: bdelacretaz
Date: Mon Apr  4 11:35:14 2016
New Revision: 1737658

URL: http://svn.apache.org/viewvc?rev=1737658&view=rev
Log:
SLING-5594 - Sling Dynamic Include module, donated by Cognifide Ltd, many thanks!

Added:
    sling/trunk/contrib/extensions/sling-dynamic-include/   (with props)
    sling/trunk/contrib/extensions/sling-dynamic-include/.gitignore
    sling/trunk/contrib/extensions/sling-dynamic-include/README.md
    sling/trunk/contrib/extensions/sling-dynamic-include/pom.xml
    sling/trunk/contrib/extensions/sling-dynamic-include/src/
    sling/trunk/contrib/extensions/sling-dynamic-include/src/main/
    sling/trunk/contrib/extensions/sling-dynamic-include/src/main/doc/
    sling/trunk/contrib/extensions/sling-dynamic-include/src/main/doc/plain-include.png   (with props)
    sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/
    sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/
    sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/
    sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/
    sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/
    sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/CacheControlFilter.java
    sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/Configuration.java   (with props)
    sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/ConfigurationWhiteboard.java
    sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/IncludeTagFilter.java
    sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/SyntheticResourceFilter.java
    sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/
    sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/IncludeGenerator.java   (with props)
    sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/IncludeGeneratorWhiteboard.java   (with props)
    sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/types/
    sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/types/EsiGenerator.java   (with props)
    sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/types/JsiGenerator.java   (with props)
    sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/types/SsiGenerator.java   (with props)
    sling/trunk/contrib/extensions/sling-dynamic-include/src/main/resources/
    sling/trunk/contrib/extensions/sling-dynamic-include/src/main/resources/generators/
    sling/trunk/contrib/extensions/sling-dynamic-include/src/main/resources/generators/jquery.html   (with props)
Modified:
    sling/trunk/contrib/pom.xml

Propchange: sling/trunk/contrib/extensions/sling-dynamic-include/
------------------------------------------------------------------------------
--- svn:ignore (added)
+++ svn:ignore Mon Apr  4 11:35:14 2016
@@ -0,0 +1,15 @@
+target
+bin
+derby.log
+*.iml
+*.ipr
+*.iws
+.settings
+.project
+.classpath
+.externalToolBuilders
+maven-eclipse.xml
+
+
+
+

Added: sling/trunk/contrib/extensions/sling-dynamic-include/.gitignore
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-dynamic-include/.gitignore?rev=1737658&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-dynamic-include/.gitignore (added)
+++ sling/trunk/contrib/extensions/sling-dynamic-include/.gitignore Mon Apr  4 11:35:14 2016
@@ -0,0 +1,5 @@
+*.class
+.classpath
+.settings
+.project
+/target

Added: sling/trunk/contrib/extensions/sling-dynamic-include/README.md
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-dynamic-include/README.md?rev=1737658&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-dynamic-include/README.md (added)
+++ sling/trunk/contrib/extensions/sling-dynamic-include/README.md Mon Apr  4 11:35:14 2016
@@ -0,0 +1,151 @@
+# Sling Dynamic Include
+
+## Purpose
+
+The purpose of the module presented here is to replace dynamic generated components (eg. current time or foreign exchange rates) with server-side include tag (eg. [SSI](http://httpd.apache.org/docs/current/howto/ssi.html) or [ESI](http://www.w3.org/TR/esi-lang)). Therefore the dispatcher is able to cache the whole page but dynamic components are generated and included with every request. Components to include are chosen in filter configuration using `resourceType` attribute.
+
+When the filter intercepts request for a component with given `resourceType`, it'll return a server-side include tag (eg. `<!--#include virtual="/path/to/resource" -->` for Apache server). However the path is extended by new selector (`nocache` by default). This is required because filter has to know when to return actual content.
+
+Components don't have to be modified in order to use this module (or even aware of its existence). It's servlet filter, installed as an OSGi bundle and it can be enabled, disabled or reconfigured without touching CQ installation.
+
+## Prerequisites
+
+* CQ / Apache Sling 2
+* Maven 2.x, 3.x
+
+## Installation
+
+Add following dependency to your project:
+
+    <dependency>
+	    <groupId>org.apache.sling</groupId>
+	    <artifactId>dynamic-include</artifactId>
+	    <version>2.2.0</version>
+    </dependency>
+
+## Configuration
+
+Filter is delivered as a standard OSGi bundle. SDI is configured via the configuration factory called *SDI Configuration*. Following properties are available:
+
+* **Enabled** - enable SDI
+* **Base path** - given SDI configuration will be enabled only for this
+  path
+* **Resource types** - which components should be replaced with tags
+* **Include type** - type of include tag (Apache SSI, ESI or Javascript)
+* **Add comment** - adds debug comment: `<!-- SDI include (path: %s, resourceType: %s) -->` to every replaced component
+* **Filter selector** - selector used to get actual content
+* **Component TTL** - time to live in seconds, set for rendered component (require Dispatcher 4.1.11+)
+* **Required header** - SDI will be enabled only if the configured header is present in the request. By default it's `Server-Agent=Communique-Dispatcher` header, added by the AEM dispatcher. You may enter just the header name only or the name and the value split with `=`.
+* **Ignore URL params** - SDI normally skips all requests containing any GET parameters. This option allows to set a list of parameters that should be ignored in the test. See the [Ignoring URL parameters](https://docs.adobe.com/docs/en/dispatcher/disp-config.html#Ignoring%20URL%20Parameters) section in the dispatcher documentation.
+* **Include path rewriting** -- enable rewriting link (according to sling mappings) that is used for dynamic content including.
+
+## Compatibility with components
+
+Filter is incompatible with following types of component:
+
+* components which handles POST requests or GET parameters,
+* synthetic components which uses suffixes (because suffix is used to pass `requestType` of the synthetic resource).
+
+If component do not generate HTML but eg. JS or binary data then remember to turn off *Comment* option in configuration.
+
+## Enabling SSI in Apache & dispatcher
+
+In order to enable SSI in Apache with dispatcher first enable `Include` mod (on Debian: `a2enmod include`). Then add `Includes` option to the `Options` directive in your virtual configuration host. After that find following lines in `dispatcher.conf` file:
+
+        <IfModule dispatcher_module>
+            SetHandler dispatcher-handler
+        </IfModule>
+
+and modify it:
+
+        <IfModule dispatcher_module>
+            SetHandler dispatcher-handler
+        </IfModule>
+        SetOutputFilter INCLUDES
+
+After setting output filter open virtualhost configuration and add `Includes` option to `Options` directive:
+
+        <Directory />
+            Options FollowSymLinks Includes
+            AllowOverride None
+        </Directory>
+        <Directory /var/www/>
+            Options Indexes FollowSymLinks MultiViews Includes
+            AllowOverride None
+            Order allow,deny
+            allow from all
+        </Directory>
+
+It's also a good idea to disable the caching for `.nocache.html` files in `dispatcher.any` config file. Just add:
+
+        /disable-nocache
+        {
+            /glob "*.nocache.html*"
+            /type "deny"
+        }
+
+at the end of the `/rules` section.
+
+## Enabling TTL in dispatcher 4.1.11+
+In order to enable TTL on Apache with dispatcher just add:
+
+	/enableTTL "1"
+
+to your dispatcher configuration.
+
+
+## Enabling ESI in Varnish
+
+Just add following lines at the beginning of the `vcl_fetch` section in `/etc/varnish/default.vcl` file:
+
+        if(req.url ~ "\.nocache.html") {
+            set beresp.ttl = 0s;
+        } else if (req.url ~ "\.html") {
+            set beresp.do_esi = true;
+        }
+
+It'll enable ESI includes in `.html` files and disable caching of the `.nocache.html` files.
+
+## JavaScript Include
+
+Dynamic Include Filter can also replace dynamic components with AJAX tags, so they are loaded by the browser. It's called JSI. In the current version jQuery framework is used. More attention is required if included component has some Javascript code. Eg. Geometrixx Carousel component won't work because it's initialization is done in page `<head>` section while the component itself is still not loaded.
+
+## Plain and synthetic resources
+
+There are two cases: the first involves including a component which is available at some URL, eg.
+
+    /content/geometrixx/en/jcr:content/carousel.html
+
+In this case, component is replaced with include tag, and `nocache` selector is added
+
+    <!--#include virtual="/content/geometrixx/en/jcr:content/carousel.nocache.html" -->
+    
+If the filter gets request with selector it'll pass it (using `doChain`) further without taking any action.
+
+![Plain include](https://raw.github.com/Cognifide/Sling-Dynamic-Include/master/src/main/doc/plain-include.png)
+
+There are also components which are created from so-called synthetic resources. Synthetic resource have some resourceType and path, but they don't have any node is JCR repository. An example is
+
+    /content/geometrixx/en/jcr:content/userinfo
+
+component with `foundation/components/userinfo` resource type. These components return 404 error if you try to make a HTTP request. SDI recognizes these components and forms a different include URL for them in which resource type is added as a suffix, eg.:
+
+    /content/geometrixx/en/jcr:content/userinfo.nocache.html/foundation/components/userinfo
+
+If filter got such request, it'll try to emulate `<sling:include>` JSP tag and includes resource with given type and `nocache` selector:
+
+    /content/geometrixx/en/jcr:content/userinfo.nocache.html
+
+Selector is necessary, because otherwise filter would again replace component with a SSI tag.
+
+# External resources
+
+* [SDI presentation](http://www.pro-vision.de/content/medialib/pro-vision/production/adaptto/2012/adaptto2012-sling-dynamic-include-tomasz-rekaweki-pdf/_jcr_content/renditions/rendition.file/adaptto2012-sling-dynamic-include-tomasz-rekaweki.pdf) on [adaptTo() 2012](http://www.pro-vision.de/de/adaptto/adaptto-2012.html)
+* [SDI blog](http://www.cognifide.com/blogs/cq/sling-dynamic-include/) post on the Cognifide website
+* See the [Apache Sling website](http://sling.apache.org/) for the Sling reference documentation. Apache Sling, Apache and Sling are trademarks of the [Apache Software Foundation](http://apache.org).
+
+# Release notes
+
+## 2.2.0
+
+\#17 Support for time-based (TTL) caching, Dispatcher 4.1.11+ required

Added: sling/trunk/contrib/extensions/sling-dynamic-include/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-dynamic-include/pom.xml?rev=1737658&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-dynamic-include/pom.xml (added)
+++ sling/trunk/contrib/extensions/sling-dynamic-include/pom.xml Mon Apr  4 11:35:14 2016
@@ -0,0 +1,141 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+    
+    http://www.apache.org/licenses/LICENSE-2.0
+    
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
+
+    <modelVersion>4.0.0</modelVersion>
+    
+    <parent>
+        <groupId>org.apache.sling</groupId>
+        <artifactId>sling</artifactId>
+        <version>26</version>
+        <relativePath/>
+    </parent>    
+    
+    <artifactId>org.apache.sling.dynamic-include</artifactId>
+    <version>2.2.1-SNAPSHOT</version>
+    <packaging>bundle</packaging>
+    
+    <name>Apache Sling Dynamic Include</name>
+    <description>Dynamic Include filter for Apache Sling</description>
+
+    <scm>
+        <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/dynamic-include</connection>
+        <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/contrib/extensions/dynamic-include</developerConnection>
+        <url>http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/dynamic-include</url>
+    </scm>    
+
+    <developers>
+        <developer>
+            <id>pacoolsky</id>
+            <name>Przemyslaw Pakulski</name>
+            <email>ppakulski@gmail.com</email>
+        </developer>
+        <developer>
+            <id>trekawek</id>
+            <name>Tomasz Rekawek</name>
+            <email>rekawek@adobe.com</email>
+        </developer>
+    </developers>
+
+    <build>
+        <plugins>
+           <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-scr-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>generate-scr-scrdescriptor</id>
+                        <goals>
+                            <goal>scr</goal>
+                        </goals>
+                    </execution>
+                </executions>
+            </plugin>        
+            <plugin>
+                <groupId>org.apache.felix</groupId>
+                <artifactId>maven-bundle-plugin</artifactId>
+                <extensions>true</extensions>
+            </plugin>
+        </plugins>
+    </build>
+
+    <dependencies>
+        <!-- osgi -->
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.core</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.osgi</groupId>
+            <artifactId>org.osgi.compendium</artifactId>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.felix</groupId>
+            <artifactId>org.apache.felix.scr.annotations</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- javax -->
+        <dependency>
+            <groupId>javax.servlet</groupId>
+            <artifactId>servlet-api</artifactId>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- sling -->
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.api</artifactId>
+            <version>2.2.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.engine</artifactId>
+            <version>2.2.0</version>
+            <scope>provided</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.sling</groupId>
+            <artifactId>org.apache.sling.commons.osgi</artifactId>
+            <version>2.2.0</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- logging -->
+        <dependency>
+            <groupId>org.slf4j</groupId>
+            <artifactId>slf4j-api</artifactId>
+            <version>1.7.0</version>
+            <scope>provided</scope>
+        </dependency>
+
+        <!-- commons -->
+        <dependency>
+            <groupId>commons-lang</groupId>
+            <artifactId>commons-lang</artifactId>
+            <version>2.4</version>
+            <scope>provided</scope>
+        </dependency>
+    </dependencies>
+
+</project>

Added: sling/trunk/contrib/extensions/sling-dynamic-include/src/main/doc/plain-include.png
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-dynamic-include/src/main/doc/plain-include.png?rev=1737658&view=auto
==============================================================================
Binary file - no diff available.

Propchange: sling/trunk/contrib/extensions/sling-dynamic-include/src/main/doc/plain-include.png
------------------------------------------------------------------------------
    svn:mime-type = application/octet-stream

Added: sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/CacheControlFilter.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/CacheControlFilter.java?rev=1737658&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/CacheControlFilter.java (added)
+++ sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/CacheControlFilter.java Mon Apr  4 11:35:14 2016
@@ -0,0 +1,72 @@
+/*-
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sling.dynamicinclude;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.sling.SlingFilter;
+import org.apache.felix.scr.annotations.sling.SlingFilterScope;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.SlingHttpServletResponse;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@SlingFilter(scope = SlingFilterScope.REQUEST, order = 0)
+public class CacheControlFilter implements Filter {
+
+    private static final String HEADER_CACHE_CONTROL = "Cache-Control";
+
+    private static final Logger LOG = LoggerFactory.getLogger(CacheControlFilter.class);
+
+    @Reference
+    private ConfigurationWhiteboard configurationWhiteboard;
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
+            ServletException {
+        final SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request;
+        final String resourceType = slingRequest.getResource().getResourceType();
+        final Configuration config = configurationWhiteboard.getConfiguration(slingRequest, resourceType);
+
+        if (config != null && config.hasTtlSet()) {
+            SlingHttpServletResponse slingResponse = (SlingHttpServletResponse) response;
+            slingResponse.setHeader(HEADER_CACHE_CONTROL, "max-age=" + config.getTtl());
+            LOG.debug("set \"{}: max-age={}\" to {}", HEADER_CACHE_CONTROL, config.getTtl(), resourceType);
+        }
+
+        chain.doFilter(request, response);
+    }
+
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException {
+    }
+
+    @Override
+    public void destroy() {
+    }
+}

Added: sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/Configuration.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/Configuration.java?rev=1737658&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/Configuration.java (added)
+++ sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/Configuration.java Mon Apr  4 11:35:14 2016
@@ -0,0 +1,188 @@
+/*-
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sling.dynamicinclude;
+
+import java.util.Arrays;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.ConfigurationPolicy;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.PropertyOption;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.commons.osgi.PropertiesUtil;
+import org.osgi.framework.Constants;
+import org.osgi.service.component.ComponentContext;
+
+/**
+ * Include filter configuration.
+ * 
+ * @author tomasz.rekawek
+ * 
+ */
+@Component(metatype = true, configurationFactory = true, label = "Apache Sling Dynamic Include - Configuration", immediate = true, policy = ConfigurationPolicy.REQUIRE)
+@Service(Configuration.class)
+@Properties({
+        @Property(name = Constants.SERVICE_VENDOR, value = "The Apache Software Foundation"),
+        @Property(name = Configuration.PROPERTY_FILTER_ENABLED, boolValue = Configuration.DEFAULT_FILTER_ENABLED, label = "Enabled", description = "Check to enable the filter"),
+        @Property(name = Configuration.PROPERTY_FILTER_PATH, value = Configuration.DEFAULT_FILTER_PATH, label = "Base path", description = "This SDI configuration will work only for this path"),
+        @Property(name = Configuration.PROPERTY_FILTER_RESOURCE_TYPES, cardinality = Integer.MAX_VALUE, label = "Resource types", description = "Filter will replace components with selected resource types"),
+        @Property(name = Configuration.PROPERTY_INCLUDE_TYPE, value = Configuration.DEFAULT_INCLUDE_TYPE, label = "Include type", description = "Type of generated include tags", options = {
+                @PropertyOption(name = "SSI", value = "Apache SSI"), @PropertyOption(name = "ESI", value = "ESI"),
+                @PropertyOption(name = "JSI", value = "Javascript") }),
+        @Property(name = Configuration.PROPERTY_ADD_COMMENT, boolValue = Configuration.DEFAULT_ADD_COMMENT, label = "Add comment", description = "Add comment to included components"),
+        @Property(name = Configuration.PROPERTY_FILTER_SELECTOR, value = Configuration.DEFAULT_FILTER_SELECTOR, label = "Filter selector", description = "Selector used to mark included resources"),
+        @Property(name = Configuration.PROPERTY_COMPONENT_TTL, label = "Component TTL", description = "\"Time to live\" cache header for rendered component (in seconds)"),
+        @Property(name = Configuration.PROPERTY_REQUIRED_HEADER, value = Configuration.DEFAULT_REQUIRED_HEADER, label = "Required header", description = "SDI will work only for requests with given header"),
+        @Property(name = Configuration.PROPERTY_IGNORE_URL_PARAMS, cardinality = Integer.MAX_VALUE, label = "Ignore URL params", description = "SDI will process the request even if it contains configured GET parameters"),
+        @Property(name = Configuration.PROPERTY_REWRITE_PATH, boolValue = Configuration.DEFAULT_REWRITE_DISABLED, label = "Include path rewriting", description = "Check to enable include path rewriting") })
+public class Configuration {
+
+    static final String PROPERTY_FILTER_PATH = "include-filter.config.path";
+
+    static final String DEFAULT_FILTER_PATH = "/content";
+
+    static final String PROPERTY_FILTER_ENABLED = "include-filter.config.enabled";
+
+    static final boolean DEFAULT_FILTER_ENABLED = false;
+
+    static final String PROPERTY_FILTER_RESOURCE_TYPES = "include-filter.config.resource-types";
+
+    static final String PROPERTY_FILTER_SELECTOR = "include-filter.config.selector";
+
+    static final String DEFAULT_FILTER_SELECTOR = "nocache";
+
+    static final String PROPERTY_COMPONENT_TTL = "include-filter.config.ttl";
+
+    static final String PROPERTY_INCLUDE_TYPE = "include-filter.config.include-type";
+
+    static final String DEFAULT_INCLUDE_TYPE = "SSI";
+
+    static final String PROPERTY_ADD_COMMENT = "include-filter.config.add_comment";
+
+    static final boolean DEFAULT_ADD_COMMENT = false;
+
+    static final String PROPERTY_REQUIRED_HEADER = "include-filter.config.required_header";
+
+    static final String DEFAULT_REQUIRED_HEADER = "Server-Agent=Communique-Dispatcher";
+
+    static final String PROPERTY_IGNORE_URL_PARAMS = "include-filter.config.ignoreUrlParams";
+
+    static final String PROPERTY_REWRITE_PATH = "include-filter.config.rewrite";
+
+    static final boolean DEFAULT_REWRITE_DISABLED = false;
+
+    private boolean isEnabled;
+
+    private String path;
+
+    private String includeSelector;
+
+    private int ttl;
+
+    private List<String> resourceTypes;
+
+    private boolean addComment;
+
+    private String includeTypeName;
+
+    private String requiredHeader;
+
+    private List<String> ignoreUrlParams;
+
+    private boolean rewritePath;
+
+    @Activate
+    public void activate(ComponentContext context, Map<String, ?> properties) {
+        isEnabled = PropertiesUtil.toBoolean(properties.get(PROPERTY_FILTER_ENABLED), DEFAULT_FILTER_ENABLED);
+        path = PropertiesUtil.toString(properties.get(PROPERTY_FILTER_PATH), DEFAULT_FILTER_PATH);
+        String[] resourceTypeList;
+        resourceTypeList = PropertiesUtil.toStringArray(properties.get(PROPERTY_FILTER_RESOURCE_TYPES), new String[0]);
+        for (int i = 0; i < resourceTypeList.length; i++) {
+            String[] s = resourceTypeList[i].split(";");
+            String name = s[0].trim();
+            resourceTypeList[i] = name;
+        }
+        this.resourceTypes = Arrays.asList(resourceTypeList);
+
+        includeSelector = PropertiesUtil.toString(properties.get(PROPERTY_FILTER_SELECTOR), DEFAULT_FILTER_SELECTOR);
+        ttl = PropertiesUtil.toInteger(properties.get(PROPERTY_COMPONENT_TTL), -1);
+        addComment = PropertiesUtil.toBoolean(properties.get(PROPERTY_ADD_COMMENT), DEFAULT_ADD_COMMENT);
+        includeTypeName = PropertiesUtil.toString(properties.get(PROPERTY_INCLUDE_TYPE), DEFAULT_INCLUDE_TYPE);
+        requiredHeader = PropertiesUtil.toString(properties.get(PROPERTY_REQUIRED_HEADER), DEFAULT_REQUIRED_HEADER);
+        ignoreUrlParams = Arrays.asList(PropertiesUtil.toStringArray(properties.get(PROPERTY_IGNORE_URL_PARAMS),
+                new String[0]));
+        rewritePath = PropertiesUtil.toBoolean(properties.get(PROPERTY_REWRITE_PATH), DEFAULT_REWRITE_DISABLED);
+    }
+
+    public String getBasePath() {
+        return path;
+    }
+
+    public boolean hasIncludeSelector(SlingHttpServletRequest request) {
+        return ArrayUtils.contains(request.getRequestPathInfo().getSelectors(), includeSelector);
+    }
+
+    public String getIncludeSelector() {
+        return includeSelector;
+    }
+
+    public boolean hasTtlSet() {
+        return ttl >= 0;
+    }
+
+    public int getTtl() {
+        return ttl;
+    }
+
+    public boolean isSupportedResourceType(String resourceType) {
+        return StringUtils.isNotBlank(resourceType) && resourceTypes.contains(resourceType);
+    }
+
+    public boolean getAddComment() {
+        return addComment;
+    }
+
+    public String getIncludeTypeName() {
+        return includeTypeName;
+    }
+
+    public boolean isEnabled() {
+        return isEnabled;
+    }
+
+    public String getRequiredHeader() {
+        return requiredHeader;
+    }
+
+    public List<String> getIgnoreUrlParams() {
+        return ignoreUrlParams;
+    }
+
+    public boolean isRewritePath() {
+        return rewritePath;
+    }
+}

Propchange: sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/Configuration.java
------------------------------------------------------------------------------
    svn:executable = *

Added: sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/ConfigurationWhiteboard.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/ConfigurationWhiteboard.java?rev=1737658&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/ConfigurationWhiteboard.java (added)
+++ sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/ConfigurationWhiteboard.java Mon Apr  4 11:35:14 2016
@@ -0,0 +1,61 @@
+/*-
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sling.dynamicinclude;
+
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.ReferencePolicy;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.SlingHttpServletRequest;
+
+@Component
+@Service(ConfigurationWhiteboard.class)
+public class ConfigurationWhiteboard {
+
+    @Reference(referenceInterface = Configuration.class, cardinality = ReferenceCardinality.OPTIONAL_MULTIPLE, policy = ReferencePolicy.DYNAMIC)
+    private Set<Configuration> configs = new CopyOnWriteArraySet<Configuration>();
+
+    public Configuration getConfiguration(SlingHttpServletRequest request, String resourceType) {
+        for (Configuration c : configs) {
+            if (isEnabled(c, request) && c.isSupportedResourceType(resourceType)) {
+                return c;
+            }
+        }
+        return null;
+    }
+
+    private boolean isEnabled(Configuration config, SlingHttpServletRequest request) {
+        final String requestPath = request.getRequestPathInfo().getResourcePath();
+        return config.isEnabled() && StringUtils.startsWith(requestPath, config.getBasePath());
+    }
+
+    protected void bindConfigs(final Configuration config) {
+        configs.add(config);
+    }
+
+    protected void unbindConfigs(final Configuration config) {
+        configs.remove(config);
+    }
+}

Added: sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/IncludeTagFilter.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/IncludeTagFilter.java?rev=1737658&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/IncludeTagFilter.java (added)
+++ sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/IncludeTagFilter.java Mon Apr  4 11:35:14 2016
@@ -0,0 +1,202 @@
+/*-
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sling.dynamicinclude;
+
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.util.Enumeration;
+import java.util.List;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.sling.SlingFilter;
+import org.apache.felix.scr.annotations.sling.SlingFilterScope;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.request.RequestPathInfo;
+import org.apache.sling.api.resource.Resource;
+import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.dynamicinclude.generator.IncludeGenerator;
+import org.apache.sling.dynamicinclude.generator.IncludeGeneratorWhiteboard;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+@SlingFilter(scope = SlingFilterScope.INCLUDE, order = -500)
+public class IncludeTagFilter implements Filter {
+
+    private static final Logger LOG = LoggerFactory.getLogger(IncludeTagFilter.class);
+
+    private static final String COMMENT = "<!-- SDI include (path: %s, resourceType: %s) -->\n";
+
+    @Reference
+    private ConfigurationWhiteboard configurationWhiteboard;
+
+    @Reference
+    private IncludeGeneratorWhiteboard generatorWhiteboard;
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
+            ServletException {
+        final SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request;
+        final String resourceType = slingRequest.getResource().getResourceType();
+
+        final Configuration config = configurationWhiteboard.getConfiguration(slingRequest, resourceType);
+        if (config == null) {
+            chain.doFilter(request, response);
+            return;
+        }
+
+        final IncludeGenerator generator = generatorWhiteboard.getGenerator(config.getIncludeTypeName());
+        if (generator == null) {
+            LOG.error("Invalid generator: " + config.getIncludeTypeName());
+            chain.doFilter(request, response);
+            return;
+        }
+
+        final PrintWriter writer = response.getWriter();
+        final String url = getUrl(config, slingRequest);
+        if (url == null) {
+            chain.doFilter(request, response);
+            return;
+        }
+
+        if (config.getAddComment()) {
+            writer.append(String.format(COMMENT, StringEscapeUtils.escapeHtml(url), resourceType));
+        }
+
+        // Only write the includes markup if the required, configurable request
+        // header is present
+        if (shouldWriteIncludes(config, slingRequest)) {
+            String include = generator.getInclude(url);
+            LOG.debug(include);
+            writer.append(include);
+        } else {
+            chain.doFilter(request, response);
+        }
+    }
+
+    private boolean shouldWriteIncludes(Configuration config, SlingHttpServletRequest request) {
+        if (requestHasParameters(config.getIgnoreUrlParams(), request)) {
+            return false;
+        }
+        final String requiredHeader = config.getRequiredHeader();
+        return StringUtils.isBlank(requiredHeader) || containsHeader(requiredHeader, request);
+    }
+
+    private boolean requestHasParameters(List<String> ignoreUrlParams, SlingHttpServletRequest request) {
+        final Enumeration<?> paramNames = request.getParameterNames();
+        while (paramNames.hasMoreElements()) {
+            final String paramName = (String) paramNames.nextElement();
+            if (!ignoreUrlParams.contains(paramName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private boolean containsHeader(String requiredHeader, SlingHttpServletRequest request) {
+        final String name, expectedValue;
+        if (StringUtils.contains(requiredHeader, '=')) {
+            final String split[] = StringUtils.split(requiredHeader, '=');
+            name = split[0];
+            expectedValue = split[1];
+        } else {
+            name = requiredHeader;
+            expectedValue = null;
+        }
+
+        final String actualValue = request.getHeader(name);
+        if (actualValue == null) {
+            return false;
+        } else if (expectedValue == null) {
+            return true;
+        } else {
+            return actualValue.equalsIgnoreCase(expectedValue);
+        }
+    }
+
+    private String getUrl(Configuration config, SlingHttpServletRequest request) {
+        String url = buildUrl(config, request);
+        if (config.isRewritePath()) {
+            url = removeQuestionMark(url);
+            url = request.getResourceResolver().map(request, url);
+        } else {
+            url = encodeJcrContentPart(url);
+            try {
+                url = new URI(null, null, url, null).toASCIIString();
+            } catch (URISyntaxException e) {
+                LOG.error("Include url is in the wrong format", e);
+                return null;
+            }
+        }
+
+        return url;
+    }
+
+    private String buildUrl(Configuration config, SlingHttpServletRequest request) {
+        final boolean synthetic = ResourceUtil.isSyntheticResource(request.getResource());
+        final Resource resource = request.getResource();
+        final StringBuilder builder = new StringBuilder();
+        final RequestPathInfo pathInfo = request.getRequestPathInfo();
+
+        final String resourcePath = pathInfo.getResourcePath();
+        builder.append(resourcePath);
+        if (pathInfo.getSelectorString() != null) {
+            builder.append('.').append(sanitize(pathInfo.getSelectorString()));
+        }
+        builder.append('.').append(config.getIncludeSelector());
+        builder.append('.').append(pathInfo.getExtension());
+        if (synthetic) {
+            builder.append('/').append(resource.getResourceType());
+        } else {
+            builder.append(sanitize(pathInfo.getSuffix()));
+        }
+        return builder.toString();
+    }
+
+    private static String sanitize(String path) {
+        return StringUtils.defaultString(path);
+    }
+
+    private static String encodeJcrContentPart(String url) {
+        return url.replace("jcr:content", "_jcr_content");
+    }
+
+    private static String removeQuestionMark(String url) {
+        return url.replaceAll("[?]", "");
+    }
+
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException {
+    }
+
+    @Override
+    public void destroy() {
+    }
+}

Added: sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/SyntheticResourceFilter.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/SyntheticResourceFilter.java?rev=1737658&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/SyntheticResourceFilter.java (added)
+++ sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/SyntheticResourceFilter.java Mon Apr  4 11:35:14 2016
@@ -0,0 +1,86 @@
+/*-
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sling.dynamicinclude;
+
+import java.io.IOException;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.RequestDispatcher;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+
+import org.apache.commons.lang.StringUtils;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Properties;
+import org.apache.felix.scr.annotations.Property;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.api.SlingHttpServletRequest;
+import org.apache.sling.api.request.RequestDispatcherOptions;
+import org.apache.sling.api.resource.ResourceUtil;
+import org.apache.sling.engine.EngineConstants;
+import org.osgi.framework.Constants;
+
+@Component(metatype = true, label = "Apache Sling Dynamic Include - Synthetic Resource Filter")
+@Service
+@Properties({
+        @Property(name = Constants.SERVICE_VENDOR, value = "The Apache Software Foundation"),
+        @Property(name = EngineConstants.SLING_FILTER_SCOPE, value = EngineConstants.FILTER_SCOPE_REQUEST, propertyPrivate = true),
+        @Property(name = Constants.SERVICE_RANKING, intValue = Integer.MIN_VALUE, propertyPrivate = false), })
+public class SyntheticResourceFilter implements Filter {
+
+    @Reference
+    private ConfigurationWhiteboard configurationWhiteboard;
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException,
+            ServletException {
+        final SlingHttpServletRequest slingRequest = (SlingHttpServletRequest) request;
+        final String resourceType = getResourceTypeFromSuffix(slingRequest);
+        final Configuration config = configurationWhiteboard.getConfiguration(slingRequest, resourceType);
+
+        if (config == null || !config.hasIncludeSelector(slingRequest)
+                || !ResourceUtil.isSyntheticResource(slingRequest.getResource())) {
+            chain.doFilter(request, response);
+            return;
+        }
+
+        final RequestDispatcherOptions options = new RequestDispatcherOptions();
+        options.setForceResourceType(resourceType);
+        final RequestDispatcher dispatcher = slingRequest.getRequestDispatcher(slingRequest.getResource(), options);
+        dispatcher.forward(request, response);
+    }
+
+    private static String getResourceTypeFromSuffix(SlingHttpServletRequest request) {
+        final String suffix = request.getRequestPathInfo().getSuffix();
+        return StringUtils.removeStart(suffix, "/");
+    }
+
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException {
+    }
+
+    @Override
+    public void destroy() {
+    }
+}

Added: sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/IncludeGenerator.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/IncludeGenerator.java?rev=1737658&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/IncludeGenerator.java (added)
+++ sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/IncludeGenerator.java Mon Apr  4 11:35:14 2016
@@ -0,0 +1,32 @@
+/*-
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sling.dynamicinclude.generator;
+
+/**
+ * Include generator interface
+ * 
+ * @author tomasz.rekawek
+ * 
+ */
+public interface IncludeGenerator {
+    String getType();
+
+    String getInclude(String url);
+}

Propchange: sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/IncludeGenerator.java
------------------------------------------------------------------------------
    svn:executable = *

Added: sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/IncludeGeneratorWhiteboard.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/IncludeGeneratorWhiteboard.java?rev=1737658&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/IncludeGeneratorWhiteboard.java (added)
+++ sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/IncludeGeneratorWhiteboard.java Mon Apr  4 11:35:14 2016
@@ -0,0 +1,61 @@
+/*-
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sling.dynamicinclude.generator;
+
+import java.util.Set;
+import java.util.concurrent.CopyOnWriteArraySet;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Reference;
+import org.apache.felix.scr.annotations.ReferenceCardinality;
+import org.apache.felix.scr.annotations.ReferencePolicy;
+import org.apache.felix.scr.annotations.Service;
+
+/**
+ * Service that provides include generator of given type.
+ * 
+ * @author tomasz.rekawek
+ */
+
+@Component
+@Service(IncludeGeneratorWhiteboard.class)
+public class IncludeGeneratorWhiteboard {
+
+    @Reference(referenceInterface = IncludeGenerator.class, cardinality = ReferenceCardinality.MANDATORY_MULTIPLE, policy = ReferencePolicy.DYNAMIC)
+    private Set<IncludeGenerator> generators = new CopyOnWriteArraySet<IncludeGenerator>();
+
+    public IncludeGenerator getGenerator(String type) {
+        for (IncludeGenerator generator : generators) {
+            if (type.equals(generator.getType())) {
+                return generator;
+            }
+        }
+        return null;
+    }
+
+    void bindGenerators(IncludeGenerator generator) {
+        generators.add(generator);
+    }
+
+    void unbindGenerators(IncludeGenerator generator) {
+        generators.remove(generator);
+    }
+
+}

Propchange: sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/IncludeGeneratorWhiteboard.java
------------------------------------------------------------------------------
    svn:executable = *

Added: sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/types/EsiGenerator.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/types/EsiGenerator.java?rev=1737658&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/types/EsiGenerator.java (added)
+++ sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/types/EsiGenerator.java Mon Apr  4 11:35:14 2016
@@ -0,0 +1,51 @@
+/*-
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sling.dynamicinclude.generator.types;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.dynamicinclude.generator.IncludeGenerator;
+
+/**
+ * ESI include generator
+ * 
+ * @author tomasz.rekawek
+ * 
+ */
+@Component
+@Service
+public class EsiGenerator implements IncludeGenerator {
+    private static final String GENERATOR_NAME = "ESI";
+
+    @Override
+    public String getType() {
+        return GENERATOR_NAME;
+    }
+
+    @Override
+    public String getInclude(String url) {
+        StringBuffer buf = new StringBuffer();
+        buf.append("<esi:include src=\"");
+        buf.append(StringEscapeUtils.escapeHtml(url));
+        buf.append("\"/>");
+        return buf.toString();
+    }
+}

Propchange: sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/types/EsiGenerator.java
------------------------------------------------------------------------------
    svn:executable = *

Added: sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/types/JsiGenerator.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/types/JsiGenerator.java?rev=1737658&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/types/JsiGenerator.java (added)
+++ sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/types/JsiGenerator.java Mon Apr  4 11:35:14 2016
@@ -0,0 +1,115 @@
+/*-
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sling.dynamicinclude.generator.types;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.UnsupportedEncodingException;
+import java.net.URL;
+
+import org.apache.commons.lang.StringEscapeUtils;
+import org.apache.felix.scr.annotations.Activate;
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.dynamicinclude.generator.IncludeGenerator;
+import org.osgi.service.component.ComponentContext;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Client side include generator - using Ajax/JQuery.
+ * 
+ * @author tomasz.rekawek
+ */
+@Component
+@Service
+public class JsiGenerator implements IncludeGenerator {
+    private static final String TEMPLATE_FILENAME = "generators/jquery.html";
+
+    private static final String UUID_FIELD = "${uniqueId}";
+
+    private static final String URL_FIELD = "${url}";
+
+    private static final Logger LOG = LoggerFactory.getLogger(JsiGenerator.class);
+
+    private static final String GENERATOR_NAME = "JSI";
+
+    private volatile int divId = 1000;
+
+    private String template;
+
+    @Activate
+    public void activate(ComponentContext ctx) {
+        URL url = ctx.getBundleContext().getBundle().getResource(TEMPLATE_FILENAME);
+        if (url == null) {
+            LOG.error("File " + TEMPLATE_FILENAME + " not found in bundle.");
+            return;
+        }
+        readTemplateFromUrl(url);
+    }
+
+    @Override
+    public String getType() {
+        return GENERATOR_NAME;
+    }
+
+    @Override
+    public String getInclude(String url) {
+        if (template == null) {
+            throw new IllegalStateException("JSI generator hasn't be initialized");
+        }
+
+        String divName;
+        synchronized (this) {
+            divName = "dynamic_include_filter_div_" + divId++;
+        }
+
+        return template.replace(UUID_FIELD, divName).replace(URL_FIELD, StringEscapeUtils.escapeJavaScript(url));
+    }
+
+    private void readTemplateFromUrl(URL url) {
+        BufferedReader br = null;
+        try {
+            InputStream in = url.openStream();
+            br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
+            StringBuilder builder = new StringBuilder();
+            String line;
+            while ((line = br.readLine()) != null) {
+                builder.append(line).append('\n');
+            }
+            template = builder.toString();
+        } catch (UnsupportedEncodingException e) {
+            LOG.error("Error while reading template", e);
+        } catch (IOException e) {
+            LOG.error("Error while reading template", e);
+        } finally {
+            try {
+                if (br != null) {
+                    br.close();
+                }
+            } catch (Exception e) {
+                LOG.error("Error while closing reader", e);
+            }
+        }
+    }
+
+}

Propchange: sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/types/JsiGenerator.java
------------------------------------------------------------------------------
    svn:executable = *

Added: sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/types/SsiGenerator.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/types/SsiGenerator.java?rev=1737658&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/types/SsiGenerator.java (added)
+++ sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/types/SsiGenerator.java Mon Apr  4 11:35:14 2016
@@ -0,0 +1,61 @@
+/*-
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.sling.dynamicinclude.generator.types;
+
+import org.apache.felix.scr.annotations.Component;
+import org.apache.felix.scr.annotations.Service;
+import org.apache.sling.dynamicinclude.generator.IncludeGenerator;
+
+/**
+ * Apache SSI include generator
+ * 
+ * @author tomasz.rekawek
+ * 
+ */
+@Component
+@Service
+public class SsiGenerator implements IncludeGenerator {
+    private static final String GENERATOR_NAME = "SSI";
+
+    @Override
+    public String getType() {
+        return GENERATOR_NAME;
+    }
+
+    @Override
+    public String getInclude(String url) {
+        StringBuffer buf = new StringBuffer();
+        buf.append("<!--#include virtual=\"");
+        buf.append(escapeForApache(url));
+        buf.append("\" -->");
+        return buf.toString();
+    }
+
+    /**
+     * Escapes $ to \$
+     * 
+     * @param url
+     *            url to escape
+     * @return escaped url
+     */
+    private Object escapeForApache(String url) {
+        return url.replace("$", "\\$");
+    }
+}

Propchange: sling/trunk/contrib/extensions/sling-dynamic-include/src/main/java/org/apache/sling/dynamicinclude/generator/types/SsiGenerator.java
------------------------------------------------------------------------------
    svn:executable = *

Added: sling/trunk/contrib/extensions/sling-dynamic-include/src/main/resources/generators/jquery.html
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/extensions/sling-dynamic-include/src/main/resources/generators/jquery.html?rev=1737658&view=auto
==============================================================================
--- sling/trunk/contrib/extensions/sling-dynamic-include/src/main/resources/generators/jquery.html (added)
+++ sling/trunk/contrib/extensions/sling-dynamic-include/src/main/resources/generators/jquery.html Mon Apr  4 11:35:14 2016
@@ -0,0 +1,26 @@
+<!--
+    Licensed to the Apache Software Foundation (ASF) under one
+    or more contributor license agreements.  See the NOTICE file
+    distributed with this work for additional information
+    regarding copyright ownership.  The ASF licenses this file
+    to you under the Apache License, Version 2.0 (the
+    "License"); you may not use this file except in compliance
+    with the License.  You may obtain a copy of the License at
+    
+    http://www.apache.org/licenses/LICENSE-2.0
+    
+    Unless required by applicable law or agreed to in writing,
+    software distributed under the License is distributed on an
+    "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+    KIND, either express or implied.  See the License for the
+    specific language governing permissions and limitations
+    under the License.
+-->
+<div id="${uniqueId}"></div>
+<script type="text/javascript">
+jQuery.get("${url}", 
+	function(data) {
+		jQuery("#${uniqueId}").replaceWith(data);
+	});
+</script>
+<noscript>Your browser does not support JavaScript. Some components may not be visible.</noscript>
\ No newline at end of file

Propchange: sling/trunk/contrib/extensions/sling-dynamic-include/src/main/resources/generators/jquery.html
------------------------------------------------------------------------------
    svn:executable = *

Modified: sling/trunk/contrib/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/pom.xml?rev=1737658&r1=1737657&r2=1737658&view=diff
==============================================================================
--- sling/trunk/contrib/pom.xml (original)
+++ sling/trunk/contrib/pom.xml Mon Apr  4 11:35:14 2016
@@ -123,6 +123,7 @@
           <module>extensions/tracer</module>
           <module>extensions/urlrewriter</module>
           <module>extensions/hapi</module>
+          <module>extensions/sling-dynamic-include</module>
 
           <module>jcr/compiler</module>
           <module>jcr/jackrabbit-client</module>