diff --git a/graylog2-server/src/main/java/org/graylog2/alerts/FormattedEmailAlertSender.java b/graylog2-server/src/main/java/org/graylog2/alerts/FormattedEmailAlertSender.java index a68f904c3961..462106af6751 100644 --- a/graylog2-server/src/main/java/org/graylog2/alerts/FormattedEmailAlertSender.java +++ b/graylog2-server/src/main/java/org/graylog2/alerts/FormattedEmailAlertSender.java @@ -48,6 +48,7 @@ import static com.google.common.base.MoreObjects.firstNonNull; import static com.google.common.base.Strings.isNullOrEmpty; +import static java.util.Objects.requireNonNull; public class FormattedEmailAlertSender implements AlertSender { private static final Logger LOG = LoggerFactory.getLogger(FormattedEmailAlertSender.class); @@ -73,7 +74,7 @@ public class FormattedEmailAlertSender implements AlertSender { "${end}" + "\n"; - private final Engine engine = new Engine(); + private final Engine templateEngine; private final NotificationService notificationService; private final NodeId nodeId; private Configuration pluginConfig; @@ -81,10 +82,14 @@ public class FormattedEmailAlertSender implements AlertSender { private final EmailConfiguration configuration; @Inject - public FormattedEmailAlertSender(EmailConfiguration configuration, NotificationService notificationService, NodeId nodeId) { - this.configuration = configuration; - this.notificationService = notificationService; - this.nodeId = nodeId; + public FormattedEmailAlertSender(EmailConfiguration configuration, + NotificationService notificationService, + NodeId nodeId, + Engine templateEngine) { + this.configuration = requireNonNull(configuration, "configuration"); + this.notificationService = requireNonNull(notificationService, "notificationService"); + this.nodeId = requireNonNull(nodeId, "nodeId"); + this.templateEngine = requireNonNull(templateEngine, "templateEngine"); } @Override @@ -102,9 +107,8 @@ String buildSubject(Stream stream, AlertCondition.CheckResult checkResult, List< } Map model = getModel(stream, checkResult, backlog); - Engine engine = new Engine(); - return engine.transform(template, model); + return templateEngine.transform(template, model); } @VisibleForTesting @@ -117,7 +121,7 @@ String buildBody(Stream stream, AlertCondition.CheckResult checkResult, List model = getModel(stream, checkResult, backlog); - return engine.transform(template, model); + return this.templateEngine.transform(template, model); } private Map getModel(Stream stream, AlertCondition.CheckResult checkResult, List backlog) { diff --git a/graylog2-server/src/main/java/org/graylog2/bindings/ServerBindings.java b/graylog2-server/src/main/java/org/graylog2/bindings/ServerBindings.java index 32270d895af7..21a9aab278e2 100644 --- a/graylog2-server/src/main/java/org/graylog2/bindings/ServerBindings.java +++ b/graylog2-server/src/main/java/org/graylog2/bindings/ServerBindings.java @@ -16,12 +16,14 @@ */ package org.graylog2.bindings; +import com.floreysoft.jmte.Engine; import com.google.inject.Scopes; import com.google.inject.assistedinject.FactoryModuleBuilder; import com.google.inject.multibindings.Multibinder; import org.apache.shiro.mgt.DefaultSecurityManager; import org.elasticsearch.client.Client; import org.elasticsearch.node.Node; +import org.glassfish.grizzly.http.server.ErrorPageGenerator; import org.graylog2.Configuration; import org.graylog2.alerts.AlertSender; import org.graylog2.alerts.EmailRecipients; @@ -63,6 +65,7 @@ import org.graylog2.plugin.inject.Graylog2Module; import org.graylog2.plugin.streams.DefaultStream; import org.graylog2.plugin.streams.Stream; +import org.graylog2.rest.GraylogErrorPageGenerator; import org.graylog2.rest.NotFoundExceptionMapper; import org.graylog2.rest.ScrollChunkWriter; import org.graylog2.rest.ValidationExceptionMapper; @@ -168,6 +171,8 @@ private void bindSingletons() { bind(ClusterStatsModule.class).asEagerSingleton(); bind(ClusterConfigService.class).to(ClusterConfigServiceImpl.class).asEagerSingleton(); bind(GrokPatternRegistry.class).in(Scopes.SINGLETON); + bind(Engine.class).toInstance(Engine.createCompilingEngine()); + bind(ErrorPageGenerator.class).to(GraylogErrorPageGenerator.class).asEagerSingleton(); bind(String[].class).annotatedWith(named("RestControllerPackages")).toInstance(new String[]{ "org.graylog2.rest.resources", diff --git a/graylog2-server/src/main/java/org/graylog2/decorators/FormatStringDecorator.java b/graylog2-server/src/main/java/org/graylog2/decorators/FormatStringDecorator.java index de9117a31d0e..bf2cc348a5e1 100644 --- a/graylog2-server/src/main/java/org/graylog2/decorators/FormatStringDecorator.java +++ b/graylog2-server/src/main/java/org/graylog2/decorators/FormatStringDecorator.java @@ -93,14 +93,14 @@ public Descriptor() { } @Inject - public FormatStringDecorator(@Assisted Decorator decorator) { + public FormatStringDecorator(@Assisted Decorator decorator, Engine templateEngine) { final String formatString = (String) requireNonNull(decorator.config().get(CK_FORMAT_STRING), CK_FORMAT_STRING + " cannot be null"); this.targetField = (String) requireNonNull(decorator.config().get(CK_TARGET_FIELD), CK_TARGET_FIELD + " cannot be null"); requireAllFields = (boolean) requireNonNull(decorator.config().get(CK_REQUIRE_ALL_FIELDS), CK_REQUIRE_ALL_FIELDS + " cannot be null"); - template = Engine.createDefaultEngine().getTemplate(formatString); + template = requireNonNull(templateEngine, "templateEngine").getTemplate(formatString); usedVariables = template.getUsedVariables(); } diff --git a/graylog2-server/src/main/java/org/graylog2/rest/GraylogErrorPageGenerator.java b/graylog2-server/src/main/java/org/graylog2/rest/GraylogErrorPageGenerator.java index d11c0e242614..e753ca486fc4 100644 --- a/graylog2-server/src/main/java/org/graylog2/rest/GraylogErrorPageGenerator.java +++ b/graylog2-server/src/main/java/org/graylog2/rest/GraylogErrorPageGenerator.java @@ -23,6 +23,7 @@ import org.glassfish.grizzly.http.server.ErrorPageGenerator; import org.glassfish.grizzly.http.server.Request; +import javax.inject.Inject; import java.io.IOException; import java.io.PrintWriter; import java.io.StringWriter; @@ -34,13 +35,14 @@ public class GraylogErrorPageGenerator implements ErrorPageGenerator { private final String template; private final Engine engine; - public GraylogErrorPageGenerator() throws IOException { - this(Resources.toString(Resources.getResource("error.html.template"), StandardCharsets.UTF_8), new Engine()); + @Inject + public GraylogErrorPageGenerator(Engine templateEngine) throws IOException { + this(Resources.toString(Resources.getResource("error.html.template"), StandardCharsets.UTF_8), templateEngine); } - public GraylogErrorPageGenerator(String template, Engine engine) { - this.template = requireNonNull(template); - this.engine = requireNonNull(engine); + private GraylogErrorPageGenerator(String template, Engine templateEngine) { + this.template = requireNonNull(template, "template"); + this.engine = requireNonNull(templateEngine, "templateEngine"); } @Override diff --git a/graylog2-server/src/main/java/org/graylog2/shared/initializers/JerseyService.java b/graylog2-server/src/main/java/org/graylog2/shared/initializers/JerseyService.java index 8be7d2279ed8..e1636aa1eba6 100644 --- a/graylog2-server/src/main/java/org/graylog2/shared/initializers/JerseyService.java +++ b/graylog2-server/src/main/java/org/graylog2/shared/initializers/JerseyService.java @@ -24,6 +24,7 @@ import com.google.common.util.concurrent.AbstractIdleService; import com.google.common.util.concurrent.ThreadFactoryBuilder; import org.glassfish.grizzly.http.CompressionConfig; +import org.glassfish.grizzly.http.server.ErrorPageGenerator; import org.glassfish.grizzly.http.server.HttpServer; import org.glassfish.grizzly.http.server.NetworkListener; import org.glassfish.grizzly.ssl.SSLContextConfigurator; @@ -84,6 +85,7 @@ import static com.codahale.metrics.MetricRegistry.name; import static com.google.common.base.MoreObjects.firstNonNull; +import static java.util.Objects.requireNonNull; public class JerseyService extends AbstractIdleService { public static final String PLUGIN_PREFIX = "/plugins"; @@ -101,6 +103,7 @@ public class JerseyService extends AbstractIdleService { private final Set pluginAuditEventTypes; private final ObjectMapper objectMapper; private final MetricRegistry metricRegistry; + private final ErrorPageGenerator errorPageGenerator; private HttpServer apiHttpServer = null; private HttpServer webHttpServer = null; @@ -115,17 +118,19 @@ public JerseyService(final Configuration configuration, @Named("RestControllerPackages") final String[] restControllerPackages, Set pluginAuditEventTypes, ObjectMapper objectMapper, - MetricRegistry metricRegistry) { - this.configuration = configuration; - this.dynamicFeatures = dynamicFeatures; - this.containerResponseFilters = containerResponseFilters; - this.exceptionMappers = exceptionMappers; - this.additionalComponents = additionalComponents; - this.pluginRestResources = pluginRestResources; - this.restControllerPackages = restControllerPackages; - this.pluginAuditEventTypes = pluginAuditEventTypes; - this.objectMapper = objectMapper; - this.metricRegistry = metricRegistry; + MetricRegistry metricRegistry, + ErrorPageGenerator errorPageGenerator) { + this.configuration = requireNonNull(configuration, "configuration"); + this.dynamicFeatures = requireNonNull(dynamicFeatures, "dynamicFeatures"); + this.containerResponseFilters = requireNonNull(containerResponseFilters, "containerResponseFilters"); + this.exceptionMappers = requireNonNull(exceptionMappers, "exceptionMappers"); + this.additionalComponents = requireNonNull(additionalComponents, "additionalComponents"); + this.pluginRestResources = requireNonNull(pluginRestResources, "pluginResources"); + this.restControllerPackages = requireNonNull(restControllerPackages, "restControllerPackages"); + this.pluginAuditEventTypes = requireNonNull(pluginAuditEventTypes, "pluginAuditEventTypes"); + this.objectMapper = requireNonNull(objectMapper, "objectMapper"); + this.metricRegistry = requireNonNull(metricRegistry, "metricRegistry"); + this.errorPageGenerator = requireNonNull(errorPageGenerator, "errorPageGenerator"); } @Override @@ -356,7 +361,7 @@ private HttpServer setUp(String namePrefix, // See "Selector runners count" at https://grizzly.java.net/bestpractices.html for details. listener.getTransport().setSelectorRunnersCount(selectorRunnersCount); - listener.setDefaultErrorPageGenerator(new GraylogErrorPageGenerator()); + listener.setDefaultErrorPageGenerator(errorPageGenerator); if(enableGzip) { final CompressionConfig compressionConfig = listener.getCompressionConfig(); diff --git a/graylog2-server/src/main/java/org/graylog2/shared/rest/resources/documentation/DocumentationBrowserResource.java b/graylog2-server/src/main/java/org/graylog2/shared/rest/resources/documentation/DocumentationBrowserResource.java index 578359624f73..b7143f634b65 100644 --- a/graylog2-server/src/main/java/org/graylog2/shared/rest/resources/documentation/DocumentationBrowserResource.java +++ b/graylog2-server/src/main/java/org/graylog2/shared/rest/resources/documentation/DocumentationBrowserResource.java @@ -46,12 +46,13 @@ public class DocumentationBrowserResource extends RestResource { private final String apiPrefix; private final ClassLoader classLoader = ClassLoader.getSystemClassLoader(); - private final Engine engine = new Engine(); + private final Engine templateEngine; @Inject - public DocumentationBrowserResource(MimetypesFileTypeMap mimeTypes, Configuration configuration) { - this.mimeTypes = requireNonNull(mimeTypes); - this.apiPrefix = configuration.getRestListenUri().getPath(); + public DocumentationBrowserResource(MimetypesFileTypeMap mimeTypes, Configuration configuration, Engine templateEngine) { + this.mimeTypes = requireNonNull(mimeTypes, "mimeTypes"); + this.apiPrefix = requireNonNull(configuration, "configuration").getRestListenUri().getPath(); + this.templateEngine = requireNonNull(templateEngine, "templateEngine"); } @GET @@ -69,7 +70,7 @@ public String index() throws IOException { final URL templateUrl = this.getClass().getResource("/swagger/index.html.template"); final String template = Resources.toString(templateUrl, StandardCharsets.UTF_8); final Map model = ImmutableMap.of("apiPrefix", apiPrefix); - return engine.transform(template, model); + return templateEngine.transform(template, model); } @GET diff --git a/graylog2-server/src/main/java/org/graylog2/web/IndexHtmlGenerator.java b/graylog2-server/src/main/java/org/graylog2/web/IndexHtmlGenerator.java index 3523505f29d2..8a0cd96907ab 100644 --- a/graylog2-server/src/main/java/org/graylog2/web/IndexHtmlGenerator.java +++ b/graylog2-server/src/main/java/org/graylog2/web/IndexHtmlGenerator.java @@ -28,13 +28,15 @@ import java.nio.charset.StandardCharsets; import java.util.Map; +import static java.util.Objects.requireNonNull; + @Singleton public class IndexHtmlGenerator { private static final String title = "Graylog Web Interface"; private final String content; @Inject - public IndexHtmlGenerator(PluginAssets pluginAssets, Configuration configuration) throws IOException { + public IndexHtmlGenerator(PluginAssets pluginAssets, Configuration configuration, Engine templateEngine) throws IOException { final URL templateUrl = this.getClass().getResource("/web-interface/index.html.template"); final String template = Resources.toString(templateUrl, StandardCharsets.UTF_8); final Map model = ImmutableMap.builder() @@ -44,8 +46,7 @@ public IndexHtmlGenerator(PluginAssets pluginAssets, Configuration configuration .put("appPrefix", configuration.getWebPrefix()) .build(); - final Engine engine = new Engine(); - this.content = engine.transform(template, model); + this.content = requireNonNull(templateEngine, "templateEngine").transform(template, model); } public String get() { diff --git a/graylog2-server/src/main/java/org/graylog2/web/resources/AppConfigResource.java b/graylog2-server/src/main/java/org/graylog2/web/resources/AppConfigResource.java index 461f84d7ac97..29711d56612f 100644 --- a/graylog2-server/src/main/java/org/graylog2/web/resources/AppConfigResource.java +++ b/graylog2-server/src/main/java/org/graylog2/web/resources/AppConfigResource.java @@ -34,14 +34,17 @@ import java.nio.charset.StandardCharsets; import java.util.Map; +import static java.util.Objects.requireNonNull; + @Path("/config.js") public class AppConfigResource { - private static final Engine engine = new Engine(); private final Configuration configuration; + private final Engine templateEngine; @Inject - public AppConfigResource(Configuration configuration) { - this.configuration = configuration; + public AppConfigResource(Configuration configuration, Engine templateEngine) { + this.configuration = requireNonNull(configuration, "configuration"); + this.templateEngine = requireNonNull(templateEngine, "templateEngine"); } @GET @@ -59,6 +62,6 @@ public String get(@Context HttpHeaders headers) { "rootTimeZone", configuration.getRootTimeZone(), "serverUri", RestTools.buildEndpointUri(headers, configuration.getWebEndpointUri()), "appPathPrefix", configuration.getWebPrefix()); - return engine.transform(template, model); + return templateEngine.transform(template, model); } } diff --git a/graylog2-server/src/test/java/org/graylog2/alerts/FormattedEmailAlertSenderTest.java b/graylog2-server/src/test/java/org/graylog2/alerts/FormattedEmailAlertSenderTest.java index 018222d8a317..7ca35fe822e1 100644 --- a/graylog2-server/src/test/java/org/graylog2/alerts/FormattedEmailAlertSenderTest.java +++ b/graylog2-server/src/test/java/org/graylog2/alerts/FormattedEmailAlertSenderTest.java @@ -16,6 +16,7 @@ */ package org.graylog2.alerts; +import com.floreysoft.jmte.Engine; import org.graylog2.configuration.EmailConfiguration; import org.graylog2.notifications.NotificationService; import org.graylog2.plugin.Message; @@ -49,10 +50,11 @@ public class FormattedEmailAlertSenderTest { private NodeId mockNodeId; private FormattedEmailAlertSender emailAlertSender; + private final Engine templateEngine = new Engine(); @Before public void setUp() throws Exception { - this.emailAlertSender = new FormattedEmailAlertSender(new EmailConfiguration(), mockNotificationService, mockNodeId); + this.emailAlertSender = new FormattedEmailAlertSender(new EmailConfiguration(), mockNotificationService, mockNodeId, templateEngine); } @Test @@ -124,7 +126,7 @@ public URI getWebInterfaceUri() { return URI.create("https://localhost"); } }; - this.emailAlertSender = new FormattedEmailAlertSender(configuration, mockNotificationService, mockNodeId); + this.emailAlertSender = new FormattedEmailAlertSender(configuration, mockNotificationService, mockNodeId, templateEngine); Stream stream = mock(Stream.class); when(stream.getId()).thenReturn("123456"); @@ -149,7 +151,7 @@ public URI getWebInterfaceUri() { return null; } }; - this.emailAlertSender = new FormattedEmailAlertSender(configuration, mockNotificationService, mockNodeId); + this.emailAlertSender = new FormattedEmailAlertSender(configuration, mockNotificationService, mockNodeId, templateEngine); Stream stream = mock(Stream.class); when(stream.getId()).thenReturn("123456"); @@ -174,7 +176,7 @@ public URI getWebInterfaceUri() { return URI.create(""); } }; - this.emailAlertSender = new FormattedEmailAlertSender(configuration, mockNotificationService, mockNodeId); + this.emailAlertSender = new FormattedEmailAlertSender(configuration, mockNotificationService, mockNodeId, templateEngine); Stream stream = mock(Stream.class); when(stream.getId()).thenReturn("123456"); @@ -193,7 +195,7 @@ public URI getWebInterfaceUri() { @Test public void defaultBodyTemplateDoesNotShowBacklogIfBacklogIsEmpty() throws Exception { - FormattedEmailAlertSender emailAlertSender = new FormattedEmailAlertSender(new EmailConfiguration(), mockNotificationService, mockNodeId); + FormattedEmailAlertSender emailAlertSender = new FormattedEmailAlertSender(new EmailConfiguration(), mockNotificationService, mockNodeId, templateEngine); Stream stream = mock(Stream.class); when(stream.getId()).thenReturn("123456"); @@ -214,7 +216,7 @@ public void defaultBodyTemplateDoesNotShowBacklogIfBacklogIsEmpty() throws Excep @Test public void defaultBodyTemplateShowsBacklogIfBacklogIsNotEmpty() throws Exception { - FormattedEmailAlertSender emailAlertSender = new FormattedEmailAlertSender(new EmailConfiguration(), mockNotificationService, mockNodeId); + FormattedEmailAlertSender emailAlertSender = new FormattedEmailAlertSender(new EmailConfiguration(), mockNotificationService, mockNodeId, templateEngine); Stream stream = mock(Stream.class); when(stream.getId()).thenReturn("123456"); diff --git a/graylog2-server/src/test/java/org/graylog2/decorators/FormatStringDecoratorTest.java b/graylog2-server/src/test/java/org/graylog2/decorators/FormatStringDecoratorTest.java index 991482b906ef..827832c21750 100644 --- a/graylog2-server/src/test/java/org/graylog2/decorators/FormatStringDecoratorTest.java +++ b/graylog2-server/src/test/java/org/graylog2/decorators/FormatStringDecoratorTest.java @@ -16,6 +16,7 @@ */ package org.graylog2.decorators; +import com.floreysoft.jmte.Engine; import com.google.common.collect.ImmutableList; import com.google.common.collect.ImmutableMap; import com.google.common.collect.ImmutableMultimap; @@ -34,13 +35,14 @@ import static org.graylog2.rest.models.messages.responses.ResultMessageSummary.create; public class FormatStringDecoratorTest { + private final Engine templateEngine = Engine.createDefaultEngine(); @Test public void testFormat() { final DecoratorImpl decorator = getDecoratorConfig("${field_a}: ${field_b}", "message", true); - final FormatStringDecorator formatStringDecorator = new FormatStringDecorator(decorator); + final FormatStringDecorator formatStringDecorator = new FormatStringDecorator(decorator, templateEngine); final SearchResponse searchResponse = getSearchResponse(); final SearchResponse response = formatStringDecorator.apply(searchResponse); @@ -56,7 +58,7 @@ public void testFormat() { public void formatAllowEmptyValues() { final DecoratorImpl decorator = getDecoratorConfig("${field_a}: ${field_b}", "message", false); - final FormatStringDecorator formatStringDecorator = new FormatStringDecorator(decorator); + final FormatStringDecorator formatStringDecorator = new FormatStringDecorator(decorator, templateEngine); final SearchResponse searchResponse = getSearchResponse(); final SearchResponse response = formatStringDecorator.apply(searchResponse);