diff --git a/scm-webapp/pom.xml b/scm-webapp/pom.xml
index 2563dbf2fa..a820c60541 100644
--- a/scm-webapp/pom.xml
+++ b/scm-webapp/pom.xml
@@ -164,6 +164,12 @@
freemarker
${freemarker.version}
+
+
+ com.github.spullara.mustache.java
+ compiler
+ ${mustache.version}
+
@@ -398,6 +404,7 @@
1.13.1
1.0
3.0.4
+ 0.8.4
gfv3ee6
diff --git a/scm-webapp/src/main/java/sonia/scm/template/MustacheTemplate.java b/scm-webapp/src/main/java/sonia/scm/template/MustacheTemplate.java
new file mode 100644
index 0000000000..e6ee64a079
--- /dev/null
+++ b/scm-webapp/src/main/java/sonia/scm/template/MustacheTemplate.java
@@ -0,0 +1,103 @@
+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.template;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.github.mustachejava.Mustache;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.Writer;
+
+import java.util.Map;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class MustacheTemplate implements Template
+{
+
+ /**
+ * the logger for MustacheTemplae
+ */
+ private static final Logger logger =
+ LoggerFactory.getLogger(MustacheTemplate.class);
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ *
+ *
+ * @param templatePath
+ * @param mustache
+ */
+ public MustacheTemplate(String templatePath, Mustache mustache)
+ {
+ this.templatePath = templatePath;
+ this.mustache = mustache;
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param writer
+ * @param environment
+ */
+ @Override
+ public void execute(Writer writer, Map environment)
+ {
+ if (logger.isDebugEnabled())
+ {
+ logger.debug("render mustache template at {}", templatePath);
+ }
+
+ mustache.execute(writer, environment);
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private Mustache mustache;
+
+ /** Field description */
+ private String templatePath;
+}
diff --git a/scm-webapp/src/main/java/sonia/scm/template/MustacheTemplateEngine.java b/scm-webapp/src/main/java/sonia/scm/template/MustacheTemplateEngine.java
new file mode 100644
index 0000000000..2127610b26
--- /dev/null
+++ b/scm-webapp/src/main/java/sonia/scm/template/MustacheTemplateEngine.java
@@ -0,0 +1,138 @@
+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.template;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.github.mustachejava.Mustache;
+import com.github.mustachejava.MustacheFactory;
+
+import com.google.inject.Inject;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+
+import javax.servlet.ServletContext;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+@DefaultEngine
+public class MustacheTemplateEngine implements TemplateEngine
+{
+
+ /** Field description */
+ public static final TemplateType TYPE = new TemplateType("mustache",
+ "Mustache", "mustache");
+
+ /**
+ * the logger for MustacheTemplateEngine
+ */
+ private static final Logger logger =
+ LoggerFactory.getLogger(MustacheTemplateEngine.class);
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param context
+ */
+ @Inject
+ public MustacheTemplateEngine(ServletContext context)
+ {
+ factory = new ServletMustacheFactory(context);
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param templatePath
+ *
+ * @return
+ *
+ * @throws IOException
+ */
+ @Override
+ public Template getTemplate(String templatePath) throws IOException
+ {
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("try to find mustache template at {}", templatePath);
+ }
+
+ Template template = null;
+ Mustache mustache = factory.compile(templatePath);
+
+ if (mustache != null)
+ {
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("return mustache template for {}", templatePath);
+ }
+
+ template = new MustacheTemplate(templatePath, mustache);
+ }
+ else if (logger.isWarnEnabled())
+ {
+ logger.warn("could not find mustache template at {}", templatePath);
+ }
+
+ return template;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public TemplateType getType()
+ {
+ return TYPE;
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private MustacheFactory factory;
+}
diff --git a/scm-webapp/src/main/java/sonia/scm/template/ServletMustacheFactory.java b/scm-webapp/src/main/java/sonia/scm/template/ServletMustacheFactory.java
new file mode 100644
index 0000000000..1ddd47797b
--- /dev/null
+++ b/scm-webapp/src/main/java/sonia/scm/template/ServletMustacheFactory.java
@@ -0,0 +1,138 @@
+/**
+ * Copyright (c) 2010, Sebastian Sdorra All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ * this list of conditions and the following disclaimer. 2. Redistributions in
+ * binary form must reproduce the above copyright notice, this list of
+ * conditions and the following disclaimer in the documentation and/or other
+ * materials provided with the distribution. 3. Neither the name of SCM-Manager;
+ * nor the names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
+ * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * http://bitbucket.org/sdorra/scm-manager
+ *
+ */
+
+
+
+package sonia.scm.template;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.github.mustachejava.DefaultMustacheFactory;
+
+import com.google.common.base.Charsets;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.BufferedReader;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+
+import javax.servlet.ServletContext;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class ServletMustacheFactory extends DefaultMustacheFactory
+{
+
+ /**
+ * the logger for ServletMustacheFactory
+ */
+ private static final Logger logger =
+ LoggerFactory.getLogger(ServletMustacheFactory.class);
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param servletContext
+ */
+ public ServletMustacheFactory(ServletContext servletContext)
+ {
+ this.servletContext = servletContext;
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param resourceName
+ *
+ * @return
+ */
+ @Override
+ public Reader getReader(String resourceName)
+ {
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("try to find resource for {}", resourceName);
+ }
+
+ Reader reader = null;
+ InputStream is = servletContext.getResourceAsStream(resourceName);
+
+ if (is == null)
+ {
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("could not find resource {} in ServletContext",
+ resourceName);
+ }
+
+ ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
+
+ if (classLoader == null)
+ {
+ classLoader = ServletMustacheFactory.class.getClassLoader();
+ }
+
+ is = classLoader.getResourceAsStream(resourceName);
+ }
+
+ if (is != null)
+ {
+ if (logger.isTraceEnabled())
+ {
+ logger.trace("found resoruce for {}, return reader", resourceName);
+ }
+
+ reader = new BufferedReader(new InputStreamReader(is, Charsets.UTF_8));
+ }
+ else if (logger.isWarnEnabled())
+ {
+ logger.warn("could not find resource {}", resourceName);
+ }
+
+ return reader;
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private ServletContext servletContext;
+}