You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@sling.apache.org by ol...@apache.org on 2014/06/05 17:12:10 UTC

svn commit: r1600678 - in /sling/trunk/contrib/scripting/thymeleaf: ./ src/ src/main/ src/main/java/ src/main/java/org/ src/main/java/org/apache/ src/main/java/org/apache/sling/ src/main/java/org/apache/sling/scripting/ src/main/java/org/apache/sling/s...

Author: olli
Date: Thu Jun  5 15:12:09 2014
New Revision: 1600678

URL: http://svn.apache.org/r1600678
Log:
SLING-3649 add initial version of Apache Sling Scripting Thymeleaf

Added:
    sling/trunk/contrib/scripting/thymeleaf/
    sling/trunk/contrib/scripting/thymeleaf/README.md
    sling/trunk/contrib/scripting/thymeleaf/pom.xml
    sling/trunk/contrib/scripting/thymeleaf/src/
    sling/trunk/contrib/scripting/thymeleaf/src/main/
    sling/trunk/contrib/scripting/thymeleaf/src/main/java/
    sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/
    sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/
    sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/
    sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/
    sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/
    sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/SlingContext.java
    sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/SlingMessageResolver.java
    sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/SlingResourceResolver.java
    sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/SlingTemplateResolver.java
    sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/ThymeleafScriptEngine.java
    sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/ThymeleafScriptEngineFactory.java
    sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/thymeleaf/
    sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/thymeleaf/templateparser/
    sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/thymeleaf/templateparser/html/
    sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/thymeleaf/templateparser/html/AbstractHtmlTemplateParser.java   (with props)
    sling/trunk/contrib/scripting/thymeleaf/src/main/resources/
    sling/trunk/contrib/scripting/thymeleaf/src/main/resources/OSGI-INF/
    sling/trunk/contrib/scripting/thymeleaf/src/main/resources/OSGI-INF/metatype/
    sling/trunk/contrib/scripting/thymeleaf/src/main/resources/OSGI-INF/metatype/metatype.properties

Added: sling/trunk/contrib/scripting/thymeleaf/README.md
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/thymeleaf/README.md?rev=1600678&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/thymeleaf/README.md (added)
+++ sling/trunk/contrib/scripting/thymeleaf/README.md Thu Jun  5 15:12:09 2014
@@ -0,0 +1,7 @@
+Apache Sling Scripting Thymeleaf
+================================
+
+scripting engine for Thymeleaf templates
+
+* http://www.thymeleaf.org
+* https://github.com/thymeleaf/thymeleaf

Added: sling/trunk/contrib/scripting/thymeleaf/pom.xml
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/thymeleaf/pom.xml?rev=1600678&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/thymeleaf/pom.xml (added)
+++ sling/trunk/contrib/scripting/thymeleaf/pom.xml Thu Jun  5 15:12:09 2014
@@ -0,0 +1,167 @@
+<?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/xsd/maven-4.0.0.xsd">
+
+  <modelVersion>4.0.0</modelVersion>
+
+  <parent>
+    <groupId>org.apache.sling</groupId>
+    <artifactId>sling</artifactId>
+    <version>20-SNAPSHOT</version>
+    <relativePath>../../../parent/pom.xml</relativePath>
+  </parent>
+
+  <artifactId>org.apache.sling.scripting.thymeleaf</artifactId>
+  <version>0.0.1-SNAPSHOT</version>
+  <packaging>bundle</packaging>
+
+  <name>Apache Sling Scripting Thymeleaf</name>
+  <description>Apache Sling Scripting Thymeleaf</description>
+
+  <properties>
+    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+    <sling.java.version>7</sling.java.version>
+  </properties>
+
+  <scm>
+    <connection>scm:svn:http://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/thymeleaf</connection>
+    <developerConnection>scm:svn:https://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/thymeleaf</developerConnection>
+    <url>http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/thymeleaf</url>
+  </scm>
+
+  <dependencies>
+    <!-- javax -->
+    <dependency>
+      <groupId>javax.servlet</groupId>
+      <artifactId>servlet-api</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <!-- OSGi -->
+    <dependency>
+      <groupId>org.osgi</groupId>
+      <artifactId>org.osgi.core</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <!-- Apache Commons -->
+    <dependency>
+      <groupId>commons-io</groupId>
+      <artifactId>commons-io</artifactId>
+      <version>2.4</version>
+      <scope>provided</scope>
+    </dependency>
+    <!-- Apache Sling -->
+    <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.api</artifactId>
+      <version>2.7.0</version>
+      <scope>provided</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.apache.sling</groupId>
+      <artifactId>org.apache.sling.scripting.api</artifactId>
+      <version>2.1.6</version>
+      <scope>provided</scope>
+    </dependency>
+    <!-- Apache Felix -->
+    <dependency>
+      <groupId>org.apache.felix</groupId>
+      <artifactId>org.apache.felix.scr.annotations</artifactId>
+      <scope>provided</scope>
+    </dependency>
+    <!-- Thymeleaf -->
+    <dependency>
+      <groupId>org.thymeleaf</groupId>
+      <artifactId>thymeleaf</artifactId>
+      <version>2.1.3.RELEASE</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>org.unbescape</groupId>
+      <artifactId>unbescape</artifactId>
+      <version>1.0</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>net.sourceforge.nekohtml</groupId>
+      <artifactId>nekohtml</artifactId>
+      <version>1.9.21</version>
+      <scope>compile</scope>
+    </dependency>
+    <dependency>
+      <groupId>xerces</groupId>
+      <artifactId>xercesImpl</artifactId>
+      <version>2.11.0</version>
+      <scope>provided</scope>
+    </dependency>
+    <!-- logging -->
+    <dependency>
+      <groupId>org.slf4j</groupId>
+      <artifactId>slf4j-api</artifactId>
+      <version>1.7.7</version>
+      <scope>provided</scope>
+    </dependency>
+  </dependencies>
+
+  <build>
+    <plugins>
+      <plugin>
+        <groupId>org.apache.maven.plugins</groupId>
+        <artifactId>maven-compiler-plugin</artifactId>
+        <version>3.1</version>
+        <configuration>
+          <source>1.7</source>
+          <target>1.7</target>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-bundle-plugin</artifactId>
+        <extensions>true</extensions>
+        <configuration>
+          <instructions>
+            <Bundle-Category>sling</Bundle-Category>
+            <Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
+            <Export-Package/>
+            <Import-Package>
+              org.apache.commons.io.input;version="1.4.9999",
+              *
+            </Import-Package>
+            <Embed-Dependency>
+              *;scope=compile;inline=true
+            </Embed-Dependency>
+            <ScriptEngine-Name>${project.name}</ScriptEngine-Name>
+            <ScriptEngine-Version>${project.version}</ScriptEngine-Version>
+            <_removeheaders>
+              Embed-Dependency,
+              Private-Package,
+              Include-Resource
+            </_removeheaders>
+          </instructions>
+        </configuration>
+      </plugin>
+      <plugin>
+        <groupId>org.apache.felix</groupId>
+        <artifactId>maven-scr-plugin</artifactId>
+      </plugin>
+    </plugins>
+  </build>
+
+</project>

Added: sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/SlingContext.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/SlingContext.java?rev=1600678&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/SlingContext.java (added)
+++ sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/SlingContext.java Thu Jun  5 15:12:09 2014
@@ -0,0 +1,50 @@
+/*
+ * 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.scripting.thymeleaf;
+
+import java.io.Reader;
+import java.util.Locale;
+import java.util.Map;
+
+import org.thymeleaf.context.Context;
+
+// TODO WebContext?
+public class SlingContext extends Context {
+
+    private final Reader reader;
+
+    public SlingContext(final Reader reader) {
+        this.reader = reader;
+    }
+
+    public SlingContext(Locale locale, final Reader reader) {
+        super(locale);
+        this.reader = reader;
+    }
+
+    public SlingContext(Locale locale, Map<String, ?> variables, final Reader reader) {
+        super(locale, variables);
+        this.reader = reader;
+    }
+
+    public Reader getReader() {
+        return reader;
+    }
+
+}

Added: sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/SlingMessageResolver.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/SlingMessageResolver.java?rev=1600678&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/SlingMessageResolver.java (added)
+++ sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/SlingMessageResolver.java Thu Jun  5 15:12:09 2014
@@ -0,0 +1,46 @@
+/*
+ * 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.scripting.thymeleaf;
+
+import org.thymeleaf.Arguments;
+import org.thymeleaf.messageresolver.IMessageResolver;
+import org.thymeleaf.messageresolver.MessageResolution;
+
+public class SlingMessageResolver implements IMessageResolver {
+
+    @Override
+    public String getName() {
+        return getClass().getSimpleName();
+    }
+
+    @Override
+    public Integer getOrder() {
+        return 0; // TODO make configurable
+    }
+
+    @Override
+    public MessageResolution resolveMessage(final Arguments arguments, final String key, final Object[] messageParameters) {
+        return new MessageResolution("TODO"); // TODO
+    }
+
+    @Override
+    public void initialize() {
+    }
+
+}

Added: sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/SlingResourceResolver.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/SlingResourceResolver.java?rev=1600678&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/SlingResourceResolver.java (added)
+++ sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/SlingResourceResolver.java Thu Jun  5 15:12:09 2014
@@ -0,0 +1,52 @@
+/*
+ * 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.scripting.thymeleaf;
+
+import java.io.InputStream;
+import java.nio.charset.StandardCharsets;
+
+import org.apache.commons.io.input.ReaderInputStream;
+import org.thymeleaf.TemplateProcessingParameters;
+import org.thymeleaf.context.IContext;
+import org.thymeleaf.exceptions.TemplateProcessingException;
+import org.thymeleaf.resourceresolver.IResourceResolver;
+import org.thymeleaf.util.Validate;
+
+public class SlingResourceResolver implements IResourceResolver {
+
+    @Override
+    public String getName() {
+        return getClass().getSimpleName();
+    }
+
+    @Override
+    public InputStream getResourceAsStream(final TemplateProcessingParameters templateProcessingParameters, final String resourceName) {
+
+        Validate.notNull(templateProcessingParameters, "Template Processing Parameters cannot be null");
+
+        final IContext context = templateProcessingParameters.getContext();
+        if (context instanceof SlingContext) {
+            final SlingContext slingContext = (SlingContext) context;
+            return new ReaderInputStream(slingContext.getReader(), StandardCharsets.UTF_8);
+        } else {
+            throw new TemplateProcessingException("Cannot handle context: " + context.getClass().getName());
+        }
+    }
+
+}

Added: sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/SlingTemplateResolver.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/SlingTemplateResolver.java?rev=1600678&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/SlingTemplateResolver.java (added)
+++ sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/SlingTemplateResolver.java Thu Jun  5 15:12:09 2014
@@ -0,0 +1,62 @@
+/*
+ * 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.scripting.thymeleaf;
+
+import java.nio.charset.StandardCharsets;
+
+import org.thymeleaf.TemplateProcessingParameters;
+import org.thymeleaf.templatemode.StandardTemplateModeHandlers;
+import org.thymeleaf.templateresolver.ITemplateResolutionValidity;
+import org.thymeleaf.templateresolver.ITemplateResolver;
+import org.thymeleaf.templateresolver.NonCacheableTemplateResolutionValidity;
+import org.thymeleaf.templateresolver.TemplateResolution;
+
+public class SlingTemplateResolver implements ITemplateResolver {
+
+    final SlingResourceResolver resourceResolver;
+
+    public SlingTemplateResolver(final SlingResourceResolver resourceResolver) {
+        this.resourceResolver = resourceResolver;
+    }
+
+    @Override
+    public String getName() {
+        return getClass().getSimpleName();
+    }
+
+    @Override
+    public Integer getOrder() {
+        return 0; // TODO make configurable
+    }
+
+    @Override
+    public TemplateResolution resolveTemplate(TemplateProcessingParameters templateProcessingParameters) {
+        final String templateName = templateProcessingParameters.getTemplateName();
+        final String resourceName = templateName; // TODO
+        final String characterEncoding = StandardCharsets.UTF_8.name();
+        final String templateMode = StandardTemplateModeHandlers.LEGACYHTML5.getTemplateModeName(); // TODO make configurable
+        final ITemplateResolutionValidity validity = new NonCacheableTemplateResolutionValidity(); // TODO
+        return new TemplateResolution(templateName, resourceName, resourceResolver, characterEncoding, templateMode, validity);
+    }
+
+    @Override
+    public void initialize() {
+    }
+
+}

Added: sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/ThymeleafScriptEngine.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/ThymeleafScriptEngine.java?rev=1600678&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/ThymeleafScriptEngine.java (added)
+++ sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/ThymeleafScriptEngine.java Thu Jun  5 15:12:09 2014
@@ -0,0 +1,67 @@
+/*
+ * 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.scripting.thymeleaf;
+
+import java.io.Reader;
+import java.util.Locale;
+
+import javax.script.Bindings;
+import javax.script.ScriptContext;
+import javax.script.ScriptEngineFactory;
+import javax.script.ScriptException;
+
+import org.apache.sling.api.scripting.SlingBindings;
+import org.apache.sling.api.scripting.SlingScriptHelper;
+import org.apache.sling.scripting.api.AbstractSlingScriptEngine;
+import org.thymeleaf.TemplateEngine;
+import org.thymeleaf.context.IContext;
+
+public class ThymeleafScriptEngine extends AbstractSlingScriptEngine {
+
+    private final TemplateEngine templateEngine;
+
+    public ThymeleafScriptEngine(final ScriptEngineFactory scriptEngineFactory, final TemplateEngine templateEngine) {
+        super(scriptEngineFactory);
+        this.templateEngine = templateEngine;
+    }
+
+    @Override
+    public Object eval(Reader reader, ScriptContext scriptContext) throws ScriptException {
+        final Bindings bindings = scriptContext.getBindings(ScriptContext.ENGINE_SCOPE);
+        final SlingScriptHelper helper = (SlingScriptHelper) bindings.get(SlingBindings.SLING);
+
+        if (helper == null) {
+            throw new ScriptException("SlingScriptHelper missing from bindings");
+        }
+
+        final Locale locale = helper.getRequest().getLocale();
+        final String scriptName = helper.getScript().getScriptResource().getPath();
+
+        try {
+            final IContext context = new SlingContext(locale, bindings, reader);
+            templateEngine.process(scriptName, context, scriptContext.getWriter());
+        } catch (Exception e) {
+            final String message = String.format("Failure rendering Thymeleaf template '%s': %s", scriptName, e.getMessage());
+            throw new ScriptException(message);
+        }
+
+        return null;
+    }
+
+}

Added: sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/ThymeleafScriptEngineFactory.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/ThymeleafScriptEngineFactory.java?rev=1600678&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/ThymeleafScriptEngineFactory.java (added)
+++ sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/apache/sling/scripting/thymeleaf/ThymeleafScriptEngineFactory.java Thu Jun  5 15:12:09 2014
@@ -0,0 +1,87 @@
+/*
+ * 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.scripting.thymeleaf;
+
+import javax.script.ScriptEngine;
+
+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.Service;
+import org.apache.sling.scripting.api.AbstractScriptEngineFactory;
+import org.osgi.framework.Constants;
+import org.thymeleaf.TemplateEngine;
+
+@Component(
+    name = "org.apache.sling.scripting.thymeleaf.ThymeleafScriptEngineFactory",
+    label = "%org.apache.sling.scripting.thymeleaf.ThymeleafScriptEngineFactory.label",
+    description = "%org.apache.sling.scripting.thymeleaf.ThymeleafScriptEngineFactory.description",
+    immediate = true,
+    metatype = true
+)
+@Service
+@Properties({
+    @Property(name = Constants.SERVICE_VENDOR, value = "The Apache Software Foundation"),
+    @Property(name = Constants.SERVICE_DESCRIPTION, value = "scripting engine for Thymeleaf templates"),
+    @Property(name = Constants.SERVICE_RANKING, intValue = 0, propertyPrivate = false)
+})
+public class ThymeleafScriptEngineFactory extends AbstractScriptEngineFactory {
+
+    private SlingResourceResolver resourceResolver;
+
+    private SlingTemplateResolver templateResolver;
+
+    private SlingMessageResolver messageResolver;
+
+    private TemplateEngine templateEngine;
+
+    public ThymeleafScriptEngineFactory() {
+        // TODO make configurable
+        setExtensions("html");
+        setMimeTypes("text/html");
+        setNames("thymeleaf");
+        setupThymeleaf();
+    }
+
+    // TODO make configurable
+    protected void setupThymeleaf() {
+        resourceResolver = new SlingResourceResolver();
+        templateResolver = new SlingTemplateResolver(resourceResolver);
+        messageResolver = new SlingMessageResolver();
+        templateEngine = new TemplateEngine();
+        templateEngine.setTemplateResolver(templateResolver);
+        templateEngine.setMessageResolver(messageResolver);
+    }
+
+    @Override
+    public String getLanguageName() {
+        return "Thymeleaf";
+    }
+
+    @Override
+    public String getLanguageVersion() {
+        return "2.1"; // TODO get version from Thymeleaf
+    }
+
+    @Override
+    public ScriptEngine getScriptEngine() {
+        return new ThymeleafScriptEngine(this, templateEngine);
+    }
+
+}

Added: sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/thymeleaf/templateparser/html/AbstractHtmlTemplateParser.java
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/thymeleaf/templateparser/html/AbstractHtmlTemplateParser.java?rev=1600678&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/thymeleaf/templateparser/html/AbstractHtmlTemplateParser.java (added)
+++ sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/thymeleaf/templateparser/html/AbstractHtmlTemplateParser.java Thu Jun  5 15:12:09 2014
@@ -0,0 +1,248 @@
+/*
+ * =============================================================================
+ *
+ *   Copyright (c) 2011-2013, The THYMELEAF team (http://www.thymeleaf.org)
+ *
+ *   Licensed 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.thymeleaf.templateparser.html;
+
+import java.io.Reader;
+import java.io.StringReader;
+import java.util.List;
+
+import org.apache.xerces.parsers.DOMParser;
+import org.cyberneko.html.HTMLConfiguration;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.thymeleaf.Configuration;
+import org.thymeleaf.dom.Document;
+import org.thymeleaf.dom.Node;
+import org.thymeleaf.exceptions.ConfigurationException;
+import org.thymeleaf.exceptions.TemplateInputException;
+import org.thymeleaf.exceptions.TemplateProcessingException;
+import org.thymeleaf.templateparser.EntityResolver;
+import org.thymeleaf.templateparser.ErrorHandler;
+import org.thymeleaf.templateparser.ITemplateParser;
+import org.thymeleaf.templateparser.TemplatePreprocessingReader;
+import org.thymeleaf.util.ResourcePool;
+import org.thymeleaf.util.StandardDOMTranslator;
+import org.xml.sax.InputSource;
+
+// NOTE: This is a slightly modified class. The nasty class loader stuff is removed to not break on OSGi.
+
+/**
+ * <p>
+ *   Document parser implementation for non-XML HTML documents.
+ * </p>
+ *
+ * @since 2.0.0
+ *
+ * @author Daniel Fern&aacute;ndez
+ */
+public abstract class AbstractHtmlTemplateParser implements ITemplateParser {
+
+    private static final int BUFFER_SIZE = 8192;
+
+    private final String templateModeName;
+    private final NekoBasedHtmlParser parser;
+
+
+    protected AbstractHtmlTemplateParser(final String templateModeName, final int poolSize) {
+        this.templateModeName = templateModeName;
+        parser = new NekoBasedHtmlParser(poolSize);
+    }
+
+
+
+
+
+    public final Document parseTemplate(final Configuration configuration, final String documentName, final Reader reader) {
+        return this.parser.parseTemplate(configuration, documentName, getTemplatePreprocessingReader(reader));
+    }
+
+
+
+
+    public final List<Node> parseFragment(final Configuration configuration, final String fragment) {
+        final String wrappedFragment = wrapFragment(fragment);
+        final Document document =
+                parseTemplate(
+                        configuration,
+                        null, // documentName
+                        new StringReader(wrappedFragment));
+        return unwrapFragment(document);
+    }
+
+
+    protected abstract String wrapFragment(final String fragment);
+    protected abstract List<Node> unwrapFragment(final Document document);
+
+
+
+
+
+    /*
+     * This is defined in a class apart so that the classloader does not always try to load
+     * neko and xerces classes that might not be in the classpath.
+     */
+    private static class NekoBasedHtmlParser {
+
+
+        private final Logger logger = LoggerFactory.getLogger(this.getClass());
+        // The org.apache.xerces.parsers.DOMParser is not used here as a type
+        // parameter to avoid the class loader to try to load this xerces class
+        // (and fail) before we control the error at the constructor.
+        private final ResourcePool<Object> pool;
+        private boolean canResetParsers = true;
+
+
+        private NekoBasedHtmlParser(final int poolSize) {
+            super();
+            this.pool = new ResourcePool<Object>(new HtmlTemplateParserFactory(), poolSize);
+        }
+
+
+
+
+        public final Document parseTemplate(final Configuration configuration, final String documentName,
+                final TemplatePreprocessingReader templateReader) {
+
+            final DOMParser domParser = (DOMParser) this.pool.allocate();
+
+            try {
+
+                domParser.setErrorHandler(ErrorHandler.INSTANCE);
+                domParser.setEntityResolver(new EntityResolver(configuration));
+
+                domParser.parse(new InputSource(templateReader));
+                final org.w3c.dom.Document domDocument = domParser.getDocument();
+
+                if (this.canResetParsers) {
+                    try {
+                        /*
+                         * Reset the parser so that it can be used again.
+                         */
+                        domParser.reset();
+                    } catch (final UnsupportedOperationException ignored) {
+                        if (this.logger.isWarnEnabled()) {
+                            this.logger.warn(
+                                    "[THYMELEAF] The HTML Parser implementation being used (\"{}\") does not implement " +
+                                        "the \"reset\" operation. This will force Thymeleaf to re-create parser instances " +
+                                        "each time they are needed for parsing templates, which is more costly. Enabling template " +
+                                        "cache is recommended, and also using a parser library which implements \"reset\" such as " +
+                                        "nekoHTML version 1.9.15 or newer.",
+                                    domParser.getClass().getName());
+                        }
+                        this.canResetParsers = false;
+                    }
+                }
+
+                return StandardDOMTranslator.translateDocument(domDocument, documentName, templateReader.getDocTypeClause());
+
+            } catch (final TemplateProcessingException e) {
+                throw e;
+            } catch (final Exception e) {
+                throw new TemplateInputException("Exception parsing document", e);
+            } finally {
+
+                if (templateReader != null) {
+                    try {
+                        templateReader.close();
+                    } catch (final Exception ignored) {
+                        // ignored
+                    }
+                }
+
+                if (this.canResetParsers) {
+                    this.pool.release(domParser);
+                } else {
+                    this.pool.discardAndReplace(domParser);
+                }
+
+            }
+        }
+
+
+    }
+
+
+
+    static class HtmlTemplateParserFactory implements ResourcePool.IResourceFactory<Object> {
+
+        HtmlTemplateParserFactory() {
+            super();
+        }
+
+
+        public Object createResource() {
+
+            try {
+
+                final HTMLConfiguration config = new HTMLConfiguration();
+
+                config.setFeature("http://xml.org/sax/features/namespaces", false);
+                config.setFeature("http://cyberneko.org/html/features/override-doctype", true);
+                config.setFeature("http://cyberneko.org/html/features/scanner/cdata-sections", true);
+
+                // Avoids the inclusion of <HTML><BODY>, etc. around template fragments. Tag balancing will only
+                // be performed inside the fragments' root nodes.
+                config.setFeature("http://cyberneko.org/html/features/balance-tags/document-fragment", true);
+
+                config.setProperty("http://cyberneko.org/html/properties/doctype/pubid", "");
+                config.setProperty("http://cyberneko.org/html/properties/doctype/sysid", "");
+                config.setProperty("http://cyberneko.org/html/properties/names/elems", "match");
+                config.setProperty("http://cyberneko.org/html/properties/names/attrs", "no-change");
+
+                return new DOMParser(config);
+
+            } catch(final Exception e) {
+                throw new ConfigurationException(
+                    "Error while creating nekoHTML-based parser for " +
+                    "LEGACYHTML5 template modes.", e);
+            }
+
+        }
+
+
+    }
+
+
+
+
+    /**
+     * @since 2.0.11
+     */
+    protected boolean shouldAddThymeleafRootToParser() {
+        return false;
+    }
+
+
+
+    /**
+     * @since 2.0.11
+     */
+    protected TemplatePreprocessingReader getTemplatePreprocessingReader(final Reader reader) {
+        if (reader instanceof TemplatePreprocessingReader) {
+            final TemplatePreprocessingReader templatePreprocessingReader = (TemplatePreprocessingReader) reader;
+            return new TemplatePreprocessingReader(
+                    templatePreprocessingReader.getInnerReader(), BUFFER_SIZE, shouldAddThymeleafRootToParser());
+        }
+        return new TemplatePreprocessingReader(reader, BUFFER_SIZE, shouldAddThymeleafRootToParser());
+    }
+
+
+
+}

Propchange: sling/trunk/contrib/scripting/thymeleaf/src/main/java/org/thymeleaf/templateparser/html/AbstractHtmlTemplateParser.java
------------------------------------------------------------------------------
    svn:executable = *

Added: sling/trunk/contrib/scripting/thymeleaf/src/main/resources/OSGI-INF/metatype/metatype.properties
URL: http://svn.apache.org/viewvc/sling/trunk/contrib/scripting/thymeleaf/src/main/resources/OSGI-INF/metatype/metatype.properties?rev=1600678&view=auto
==============================================================================
--- sling/trunk/contrib/scripting/thymeleaf/src/main/resources/OSGI-INF/metatype/metatype.properties (added)
+++ sling/trunk/contrib/scripting/thymeleaf/src/main/resources/OSGI-INF/metatype/metatype.properties Thu Jun  5 15:12:09 2014
@@ -0,0 +1,24 @@
+#
+#  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.
+#
+
+service.ranking.name = service ranking
+service.ranking.description = service property for identifying the service's ranking number
+
+org.apache.sling.scripting.thymeleaf.ThymeleafScriptEngineFactory.label = Apache Sling Scripting Thymeleaf
+org.apache.sling.scripting.thymeleaf.ThymeleafScriptEngineFactory.description = scripting engine for Thymeleaf templates