make PluginLoader dependency of MustacheTemplateEngine optional

This commit is contained in:
Sebastian Sdorra
2019-06-12 17:04:32 +02:00
parent e4b187a393
commit 4c91ef0100
3 changed files with 57 additions and 36 deletions

View File

@@ -37,27 +37,22 @@ package sonia.scm.template;
import com.github.mustachejava.Mustache; import com.github.mustachejava.Mustache;
import com.github.mustachejava.MustacheException; import com.github.mustachejava.MustacheException;
import com.google.common.base.Throwables; import com.google.common.base.Throwables;
import com.google.common.util.concurrent.ThreadFactoryBuilder; import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.google.common.util.concurrent.UncheckedExecutionException; import com.google.common.util.concurrent.UncheckedExecutionException;
import com.google.inject.Inject; import com.google.inject.Inject;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import sonia.scm.Default; import sonia.scm.Default;
import sonia.scm.plugin.PluginLoader; import sonia.scm.plugin.PluginLoader;
//~--- JDK imports ------------------------------------------------------------ import javax.servlet.ServletContext;
import java.io.IOException; import java.io.IOException;
import java.io.Reader; import java.io.Reader;
import java.util.concurrent.Executors; import java.util.concurrent.Executors;
import java.util.concurrent.ThreadFactory; import java.util.concurrent.ThreadFactory;
import javax.servlet.ServletContext; //~--- JDK imports ------------------------------------------------------------
/** /**
* *
@@ -67,6 +62,14 @@ import javax.servlet.ServletContext;
public class MustacheTemplateEngine implements TemplateEngine public class MustacheTemplateEngine implements TemplateEngine
{ {
/**
* Used to implement optional injection for the PluginLoader.
* @see <a href="https://github.com/google/guice/wiki/FrequentlyAskedQuestions#how-can-i-inject-optional-parameters-into-a-constructor">Optional Injection</a>
*/
static class PluginLoaderHolder {
@Inject(optional = true) PluginLoader pluginLoader;
}
/** Field description */ /** Field description */
public static final TemplateType TYPE = new TemplateType("mustache", public static final TemplateType TYPE = new TemplateType("mustache",
"Mustache", "mustache"); "Mustache", "mustache");
@@ -87,13 +90,12 @@ public class MustacheTemplateEngine implements TemplateEngine
* *
* *
* @param context * @param context
* @param pluginLoader * @param pluginLoaderHolder
*/ */
@Inject @Inject
public MustacheTemplateEngine(@Default ServletContext context, public MustacheTemplateEngine(@Default ServletContext context, PluginLoaderHolder pluginLoaderHolder)
PluginLoader pluginLoader)
{ {
factory = new ServletMustacheFactory(context, pluginLoader); factory = new ServletMustacheFactory(context, createClassLoader(pluginLoaderHolder.pluginLoader));
ThreadFactory threadFactory = ThreadFactory threadFactory =
new ThreadFactoryBuilder().setNameFormat(THREAD_NAME).build(); new ThreadFactoryBuilder().setNameFormat(THREAD_NAME).build();
@@ -101,6 +103,13 @@ public class MustacheTemplateEngine implements TemplateEngine
factory.setExecutorService(Executors.newCachedThreadPool(threadFactory)); factory.setExecutorService(Executors.newCachedThreadPool(threadFactory));
} }
private ClassLoader createClassLoader(PluginLoader pluginLoader) {
if (pluginLoader == null) {
return Thread.currentThread().getContextClassLoader();
}
return pluginLoader.getUberClassLoader();
}
//~--- get methods ---------------------------------------------------------- //~--- get methods ----------------------------------------------------------
/** /**
@@ -112,12 +121,9 @@ public class MustacheTemplateEngine implements TemplateEngine
* *
* @return * @return
* *
* @throws IOException
*/ */
@Override @Override
public Template getTemplate(String templateIdentifier, Reader reader) public Template getTemplate(String templateIdentifier, Reader reader) {
throws IOException
{
if (logger.isTraceEnabled()) if (logger.isTraceEnabled())
{ {
logger.trace("try to create mustache template from reader with id {}", logger.trace("try to create mustache template from reader with id {}",

View File

@@ -36,22 +36,17 @@ package sonia.scm.template;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
import com.github.mustachejava.DefaultMustacheFactory; import com.github.mustachejava.DefaultMustacheFactory;
import com.google.common.base.Charsets; import com.google.common.base.Charsets;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import sonia.scm.plugin.PluginLoader; import javax.servlet.ServletContext;
//~--- JDK imports ------------------------------------------------------------
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.InputStream; import java.io.InputStream;
import java.io.InputStreamReader; import java.io.InputStreamReader;
import java.io.Reader; import java.io.Reader;
import javax.servlet.ServletContext; //~--- JDK imports ------------------------------------------------------------
/** /**
* *
@@ -73,13 +68,12 @@ public class ServletMustacheFactory extends DefaultMustacheFactory
* *
* *
* @param servletContext * @param servletContext
* @param pluginLoader * @param classLoader
*/ */
public ServletMustacheFactory(ServletContext servletContext, public ServletMustacheFactory(ServletContext servletContext, ClassLoader classLoader)
PluginLoader pluginLoader)
{ {
this.servletContext = servletContext; this.servletContext = servletContext;
this.pluginLoader = pluginLoader; this.classLoader = classLoader;
} }
//~--- get methods ---------------------------------------------------------- //~--- get methods ----------------------------------------------------------
@@ -116,7 +110,7 @@ public class ServletMustacheFactory extends DefaultMustacheFactory
resourceName = resourceName.substring(1); resourceName = resourceName.substring(1);
} }
is = pluginLoader.getUberClassLoader().getResourceAsStream(resourceName); is = classLoader.getResourceAsStream(resourceName);
} }
if (is != null) if (is != null)
@@ -144,9 +138,8 @@ public class ServletMustacheFactory extends DefaultMustacheFactory
//~--- fields --------------------------------------------------------------- //~--- fields ---------------------------------------------------------------
/** Field description */
private final PluginLoader pluginLoader;
/** Field description */ /** Field description */
private ServletContext servletContext; private ServletContext servletContext;
private ClassLoader classLoader;
} }

View File

@@ -35,16 +35,21 @@ package sonia.scm.template;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
import com.google.common.collect.ImmutableMap;
import org.assertj.core.api.Assertions;
import org.junit.Test;
import sonia.scm.plugin.PluginLoader; import sonia.scm.plugin.PluginLoader;
import static org.mockito.Mockito.*; import javax.servlet.ServletContext;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
import java.io.InputStream;
import javax.servlet.ServletContext;
/** /**
* *
* @author Sebastian Sdorra * @author Sebastian Sdorra
@@ -68,7 +73,10 @@ public class MustacheTemplateEngineTest extends TemplateEngineTestBase
when(loader.getUberClassLoader()).thenReturn( when(loader.getUberClassLoader()).thenReturn(
Thread.currentThread().getContextClassLoader()); Thread.currentThread().getContextClassLoader());
return new MustacheTemplateEngine(context, loader); MustacheTemplateEngine.PluginLoaderHolder holder = new MustacheTemplateEngine.PluginLoaderHolder();
holder.pluginLoader = loader;
return new MustacheTemplateEngine(context, holder);
} }
//~--- get methods ---------------------------------------------------------- //~--- get methods ----------------------------------------------------------
@@ -116,4 +124,18 @@ public class MustacheTemplateEngineTest extends TemplateEngineTestBase
return MustacheTemplateEngineTest.class.getResourceAsStream( return MustacheTemplateEngineTest.class.getResourceAsStream(
"/sonia/scm/template/".concat(resource).concat(".mustache")); "/sonia/scm/template/".concat(resource).concat(".mustache"));
} }
@Test
public void testCreateEngineWithoutPluginLoader() throws IOException {
ServletContext context = mock(ServletContext.class);
MustacheTemplateEngine.PluginLoaderHolder holder = new MustacheTemplateEngine.PluginLoaderHolder();
MustacheTemplateEngine engine = new MustacheTemplateEngine(context, holder);
Template template = engine.getTemplate(getTemplateResource());
StringWriter writer = new StringWriter();
template.execute(writer, ImmutableMap.of("name", "World"));
Assertions.assertThat(writer.toString()).isEqualTo("Hello World!");
}
} }