/* * Copyright (C) 2008-2023, Juick * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU Affero General Public License as * published by the Free Software Foundation, either version 3 of the * License, or (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see . */ package com.juick.config; import java.net.MalformedURLException; import java.nio.charset.StandardCharsets; import java.nio.file.Paths; import java.util.List; import java.util.concurrent.TimeUnit; import jakarta.inject.Inject; import com.juick.service.UserService; import com.juick.www.VisitorArgumentResolver; import com.mitchellbosecke.pebble.extension.FormatterExtension; import io.pebbletemplates.pebble.PebbleEngine; import io.pebbletemplates.pebble.loader.ClasspathLoader; import io.pebbletemplates.pebble.loader.Loader; import io.pebbletemplates.spring.extension.SpringExtension; import io.pebbletemplates.spring.servlet.PebbleViewResolver; import jakarta.annotation.PostConstruct; import org.springframework.beans.factory.annotation.Value; import org.springframework.cache.annotation.EnableCaching; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.core.convert.converter.Converter; import org.springframework.format.FormatterRegistry; import org.springframework.http.CacheControl; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.scheduling.annotation.EnableScheduling; import org.springframework.web.method.support.HandlerMethodArgumentResolver; import org.springframework.web.servlet.ViewResolver; import org.springframework.web.servlet.config.annotation.ResourceHandlerRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; import org.springframework.web.servlet.resource.VersionResourceResolver; @Configuration @EnableCaching @EnableAsync(proxyTargetClass = true) @EnableScheduling public class WebConfig implements WebMvcConfigurer { @Value("${storage_path:#{systemProperties['java.io.tmpdir']}}") private String baseDir; @Inject private List> converters; @Inject private UserService userService; private boolean testsAreRunning = false; private boolean devToolsArePresent = false; @PostConstruct public void initConfiguration() { try { Class.forName("org.springframework.boot.devtools.livereload.Connection"); devToolsArePresent = true; } catch (ClassNotFoundException e) { // release mode } for (StackTraceElement s : Thread.currentThread().getStackTrace()) { if (s.getClassName().contains("org.springframework.boot.test.context.SpringBootContextLoader")) { testsAreRunning = true; } } } @Override public void addFormatters(FormatterRegistry registry) { for (Converter converter : converters) { registry.addConverter(converter); } } @Bean HandlerMethodArgumentResolver visitorArgumentResolver() { return new VisitorArgumentResolver(userService); } @Override public void addArgumentResolvers(List resolvers) { resolvers.add(visitorArgumentResolver()); } @Bean Loader templateLoader() { return new ClasspathLoader(); } @Bean SpringExtension springExtension() { return new SpringExtension(null); } @Bean PebbleEngine pebbleEngine() { return new PebbleEngine.Builder() .loader(this.templateLoader()) .cacheActive(!devToolsArePresent) .extension(springExtension()) .extension(new FormatterExtension()) .newLineTrimming(false) .strictVariables(true) .build(); } @Bean ViewResolver viewResolver() { PebbleViewResolver viewResolver = new PebbleViewResolver(pebbleEngine()); viewResolver.setPrefix("templates"); viewResolver.setSuffix(".html"); viewResolver.setCharacterEncoding(StandardCharsets.UTF_8.name()); viewResolver.setExposeRequestAttributes(true); return viewResolver; } @Override public void addResourceHandlers(ResourceHandlerRegistry registry) { try { if (devToolsArePresent && !testsAreRunning) { registry .addResourceHandler("/**", "/i/a/**") .addResourceLocations("classpath:/static/", Paths.get(baseDir, "/i/a/").toUri().toURL().toString()); } else { registry .addResourceHandler("/**", "/i/a/**") .addResourceLocations("classpath:/static/", Paths.get(baseDir, "/i/a/").toUri().toURL().toString()) .setCacheControl(CacheControl.maxAge(365, TimeUnit.DAYS)) .resourceChain(false) .addResolver(new VersionResourceResolver().addContentVersionStrategy("/**", "/i/a/**")); } } catch (MalformedURLException e) { e.printStackTrace(); } } }