/** {@inheritDoc} */ @Override public void init(final FilterConfig filterConfig) throws ServletException { servletContext = filterConfig.getServletContext(); templateEngine = new TemplateEngine(); templateEngine.setTemplateResolver(createTemplateResolver()); templateEngine.setDialect(new WuicDialect()); }
@Override protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException { TemplateEngine engine = TemplateEngineUtil.getTemplateEngine(request.getServletContext()); WebContext context = new WebContext(request, response, request.getServletContext()); context.setVariable("recipient", "World"); engine.process("index.html", context, response.getWriter()); }
@Test public void useDataDialect() throws Exception { this.context.register( ThymeleafAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class); this.context.refresh(); TemplateEngine engine = this.context.getBean(TemplateEngine.class); Context attrs = new Context(Locale.UK, Collections.singletonMap("foo", "bar")); String result = engine.process("data-dialect", attrs); assertEquals("<html><body data-foo=\"bar\"></body></html>", result); }
@Test public void useJava8TimeDialect() throws Exception { this.context.register( ThymeleafAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class); this.context.refresh(); TemplateEngine engine = this.context.getBean(TemplateEngine.class); Context attrs = new Context(Locale.UK); String result = engine.process("java8time-dialect", attrs); assertThat(result).isEqualTo("<html><body>2015-11-24</body></html>"); }
@Test public void renderTemplate() throws Exception { this.context.register( ThymeleafAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class); this.context.refresh(); TemplateEngine engine = this.context.getBean(TemplateEngine.class); Context attrs = new Context(Locale.UK, Collections.singletonMap("foo", "bar")); String result = engine.process("home", attrs); assertThat(result).isEqualTo("<html><body>bar</body></html>"); }
@Test public void createFromConfigClass() throws Exception { EnvironmentTestUtils.addEnvironment( this.context, "spring.thymeleaf.mode:XHTML", "spring.thymeleaf.suffix:"); this.context.register( ThymeleafAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class); this.context.refresh(); TemplateEngine engine = this.context.getBean(TemplateEngine.class); Context attrs = new Context(Locale.UK, Collections.singletonMap("foo", "bar")); String result = engine.process("template.txt", attrs); assertThat(result).isEqualTo("<html>bar</html>"); }
@Override public String generatePageHtml(ITestPage test) { TemplateResolver templateResolver = new ClassLoaderTemplateResolver(); templateResolver.setTemplateMode("HTML5"); templateResolver.setCharacterEncoding("UTF-8"); TemplateEngine templateEngine = new TemplateEngine(); templateEngine.setTemplateResolver(templateResolver); Locale locale = LocaleUtils.toLocale("fr"); final Context ctx = new Context(locale); ctx.setVariable("test", test); String htmlOutput = templateEngine.process("new_test_report_template.html", ctx); return htmlOutput; }
@Test public void renderNonWebAppTemplate() throws Exception { AnnotationConfigApplicationContext context = new AnnotationConfigApplicationContext( ThymeleafAutoConfiguration.class, PropertyPlaceholderAutoConfiguration.class); assertThat(context.getBeanNamesForType(ViewResolver.class).length).isEqualTo(0); try { TemplateEngine engine = context.getBean(TemplateEngine.class); Context attrs = new Context(Locale.UK, Collections.singletonMap("greeting", "Hello World")); String result = engine.process("message", attrs); assertThat(result).contains("Hello World"); } finally { context.close(); } }
@Async @Override public void enviarMailCambioContraseña(String nombre, String email, String token, Locale locale) { try { final Context ctx = new Context(locale); ctx.setVariable("nombre", nombre); ctx.setVariable("token", token); ctx.setVariable("lenguaje", locale.getLanguage()); final MimeMessage mimeMessage = mailSender.createMimeMessage(); final MimeMessageHelper message = new MimeMessageHelper(mimeMessage, "UTF-8"); message.setSubject(messageSource.getMessage("reset.email.titulo", null, locale)); message.setFrom("*****@*****.**", "Cudú"); message.setTo(email); final String htmlContent = templateEngine.process("resetpassword", ctx); message.setText(htmlContent, true); mailSender.send(mimeMessage); } catch (Exception e) { String correlationId = UUID.randomUUID().toString(); Marker marker = MarkerFactory.getMarker("ENVIO_EMAIL"); logger.error( marker, "Error enviando email. Token: " + token + ", CorrelationId: " + correlationId, e); eventPublisher.publishEvent(new EmailErrorApplicationEvent(email, correlationId)); } }
@Test public void testJavaScript() { TemplateEngine engine = createWisdomEngine(); Context context = new Context(); context.setVariable("test", "test"); FakeRouter router = new FakeRouter(); Controller controller = new FakeController(); router.addController(controller); context.setVariable(Routes.ROUTES_VAR, new Routes(router, controller)); String processed = engine.process("templates/javascript.thl.html", context); assertThat(processed).containsIgnoringCase("var t = 'test';"); assertThat(processed).containsIgnoringCase("var url = '/';"); assertThat(processed).containsIgnoringCase("$(document).ready(function () {"); }
@CacheEvict(value = "users", allEntries = true) public List<UserInvitation> inviteUsers( UserInvitationCreateRequest form, BindingResult result, AuthorizedUser authorizedUser) throws MessagingException { String[] recipients = StringUtils.commaDelimitedListToStringArray(form.getInvitees()); LocalDateTime now = LocalDateTime.now(); List<UserInvitation> invitations = new ArrayList<>(); for (String recipient : recipients) { UserInvitation invitation = new UserInvitation(); invitation.setEmail(recipient); invitation.setMessage(form.getMessage()); invitation.setExpiredAt(now.plusHours(72)); invitation.setCreatedAt(now); invitation.setCreatedBy(authorizedUser.toString()); invitation.setUpdatedAt(now); invitation.setUpdatedBy(authorizedUser.toString()); invitation = userInvitationRepository.saveAndFlush(invitation); invitations.add(invitation); } Blog blog = blogService.readBlogById(Blog.DEFAULT_ID); for (UserInvitation invitation : invitations) { String websiteTitle = blog.getTitle(LocaleContextHolder.getLocale().getLanguage()); String signupLink = ServletUriComponentsBuilder.fromCurrentContextPath() .path("/_admin/signup") .queryParam("token", invitation.getToken()) .buildAndExpand() .toString(); final Context ctx = new Context(LocaleContextHolder.getLocale()); ctx.setVariable("websiteTitle", websiteTitle); ctx.setVariable("authorizedUser", authorizedUser); ctx.setVariable("signupLink", signupLink); ctx.setVariable("invitation", invitation); final MimeMessage mimeMessage = mailSender.createMimeMessage(); final MimeMessageHelper message = new MimeMessageHelper(mimeMessage, true, "UTF-8"); // true = multipart message.setSubject( MessageFormat.format( messageSourceAccessor.getMessage( "InvitationMessageTitle", LocaleContextHolder.getLocale()), authorizedUser.toString(), websiteTitle)); message.setFrom(authorizedUser.getEmail()); message.setTo(invitation.getEmail()); final String htmlContent = templateEngine.process("user-invite", ctx); message.setText(htmlContent, true); // true = isHtml mailSender.send(mimeMessage); } return invitations; }
public PasswordResetToken createPasswordResetToken(PasswordResetTokenCreateRequest request) { User user = userRepository.findByEmail(request.getEmail()); if (user == null) { throw new EmailNotFoundException(); } LocalDateTime now = LocalDateTime.now(); PasswordResetToken passwordResetToken = new PasswordResetToken(); passwordResetToken.setUser(user); passwordResetToken.setEmail(user.getEmail()); passwordResetToken.setExpiredAt(now.plusHours(24)); passwordResetToken.setCreatedAt(now); passwordResetToken.setCreatedBy(user.toString()); passwordResetToken.setUpdatedAt(now); passwordResetToken.setUpdatedBy(user.toString()); passwordResetToken = passwordResetTokenRepository.saveAndFlush(passwordResetToken); try { Blog blog = blogService.readBlogById(Blog.DEFAULT_ID); String blogTitle = blog.getTitle(LocaleContextHolder.getLocale().getLanguage()); ServletUriComponentsBuilder builder = ServletUriComponentsBuilder.fromCurrentContextPath(); if (blog.isMultiLanguage()) { builder.path("/{language}"); } builder.path("/password-reset"); builder.path("/{token}"); Map<String, Object> urlVariables = new LinkedHashMap<>(); urlVariables.put("language", request.getLanguage()); urlVariables.put("token", passwordResetToken.getToken()); String resetLink = builder.buildAndExpand(urlVariables).toString(); Context ctx = new Context(LocaleContextHolder.getLocale()); ctx.setVariable("passwordResetToken", passwordResetToken); ctx.setVariable("resetLink", resetLink); MimeMessage mimeMessage = mailSender.createMimeMessage(); MimeMessageHelper message = new MimeMessageHelper(mimeMessage, true, "UTF-8"); // true = multipart message.setSubject( MessageFormat.format( messageSourceAccessor.getMessage( "PasswordResetSubject", LocaleContextHolder.getLocale()), blogTitle)); message.setFrom(mailProperties.getProperties().get("mail.from")); message.setTo(passwordResetToken.getEmail()); String htmlContent = templateEngine.process("password-reset", ctx); message.setText(htmlContent, true); // true = isHtml mailSender.send(mimeMessage); } catch (MessagingException e) { throw new ServiceException(e); } return passwordResetToken; }
/** {@inheritDoc} */ @Override public void doFilter( final ServletRequest request, final ServletResponse response, final FilterChain chain) throws IOException, ServletException { try { templateEngine.process("index", createContext(request, response), response.getWriter()); } catch (Exception e) { throw new ServletException(e); } }
@CacheEvict(value = "users", allEntries = true) public User updatePassword(PasswordUpdateRequest request, PasswordResetToken passwordResetToken) { User user = userRepository.findByIdForUpdate(request.getUserId()); if (user == null) { throw new IllegalArgumentException("The user does not exist"); } PasswordEncoder passwordEncoder = new StandardPasswordEncoder(); user.setLoginPassword(passwordEncoder.encode(request.getPassword())); user.setUpdatedAt(LocalDateTime.now()); user.setUpdatedBy(passwordResetToken.getUser().toString()); user = userRepository.saveAndFlush(user); passwordResetTokenRepository.delete(passwordResetToken); try { Blog blog = blogService.readBlogById(Blog.DEFAULT_ID); String blogTitle = blog.getTitle(LocaleContextHolder.getLocale().getLanguage()); ServletUriComponentsBuilder builder = ServletUriComponentsBuilder.fromCurrentContextPath(); if (blog.isMultiLanguage()) { builder.path("/{language}"); } builder.path("/login"); Map<String, Object> urlVariables = new LinkedHashMap<>(); urlVariables.put("language", request.getLanguage()); urlVariables.put("token", passwordResetToken.getToken()); String loginLink = builder.buildAndExpand(urlVariables).toString(); Context ctx = new Context(LocaleContextHolder.getLocale()); ctx.setVariable("passwordResetToken", passwordResetToken); ctx.setVariable("resetLink", loginLink); MimeMessage mimeMessage = mailSender.createMimeMessage(); MimeMessageHelper message = new MimeMessageHelper(mimeMessage, true, "UTF-8"); // true = multipart message.setSubject( MessageFormat.format( messageSourceAccessor.getMessage( "PasswordChangedSubject", LocaleContextHolder.getLocale()), blogTitle)); message.setFrom(mailProperties.getProperties().get("mail.from")); message.setTo(passwordResetToken.getEmail()); String htmlContent = templateEngine.process("password-changed", ctx); message.setText(htmlContent, true); // true = isHtml mailSender.send(mimeMessage); } catch (MessagingException e) { throw new ServiceException(e); } return user; }
@Override public int read(final char[] cbuf) throws IOException { if (readerLogger.isTraceEnabled()) { readerLogger.trace( "[THYMELEAF][TEMPLATEPREPROCESSINGREADER][{}] CALLING read(char[] cbuf). Will be delegated to read(cbuf, 0, cbuf.length).", new Object[] {TemplateEngine.threadIndex()}); } return read(cbuf, 0, cbuf.length); }
@Override public void processView(ViewEngineContext context) throws ViewEngineException { try { HttpServletRequest request = context.getRequest(); HttpServletResponse response = context.getResponse(); WebContext ctx = new WebContext(request, response, servletContext, request.getLocale()); ctx.setVariables(context.getModels()); engine.process(resolveView(context), ctx, response.getWriter()); } catch (IOException e) { throw new ViewEngineException(e); } }
public void setResponse(Pair<ABSString, ABS.StdLib.List<ABSValue>> pair) throws Exception { TemplateResolver templateResolver = new TemplateResolver(); templateResolver.setTemplateMode("HTML5"); templateResolver.setSuffix(".html"); templateResolver.setResourceResolver(new ResourceResolver()); TemplateEngine templateEngine = new TemplateEngine(); templateEngine.setTemplateResolver(templateResolver); List_Cons<ABSValue> data; if (pair != null) { String view = DataTransformer.convertABSStringToJavaString((ABSString) pair.getArg(0)); Context ctx = new Context(); if (!(pair.getArg(1) instanceof List_Nil)) { data = (List_Cons<ABSValue>) pair.getArg(1); ArrayList<Object> dataModels = DataTransformer.convertABSListToJavaList(data); if (dataModels.size() > 1) { ctx.setVariable("dataList", dataModels); } else { ctx.setVariable("data", dataModels.get(0)); } } ctx.setVariable("requestMethod", this.request.getMethod()); ctx.setVariable("requestURI", this.request.getRequestURI()); ctx.setVariable("requestContextPath", this.request.getContextPath()); ctx.setVariable( "requestRoute", this.getRoute(request.getRequestURI(), request.getContextPath())); this.response = templateEngine.process(view, ctx); } else { this.response = "<h3>ERROR 404: PAGE NOT FOUND</h3>"; this.response += "<span style='font-size:0.8em;'>ABS Server: " + new Date() + "</span><br />"; } }
@Override public Content parse(String templateName, Context ctx) throws ParseException { try { LOG.debug("Parsing Thymeleaf template {} with context {}...", templateName, ctx); String result = engine.process(templateName, contextConverter.convert(ctx)); LOG.debug("Template {} successfully parsed with context {}. Result:", templateName); LOG.debug(result); return new StringContent(result); } catch (TemplateEngineException e) { throw new ParseException("Failed to parse template with thymeleaf", templateName, ctx, e); } catch (ContextException e) { throw new ParseException( "Failed to parse template with thymeleaf due to conversion error", templateName, ctx, e); } }
@Override public int read() throws IOException { if (readerLogger.isTraceEnabled()) { readerLogger.trace( "[THYMELEAF][TEMPLATEPREPROCESSINGREADER][{}] CALLING read(). Will be delegated to read(char[], 0, 1).", new Object[] {TemplateEngine.threadIndex()}); } final char[] cbuf = new char[1]; final int res = read(cbuf, 0, 1); if (res <= 0) { return res; } return cbuf[0]; }
protected IBaseResource addCommonParams( HttpServletRequest theServletRequest, final HomeRequest theRequest, final ModelMap theModel) { if (myConfig.getDebugTemplatesMode()) { myTemplateEngine.getCacheManager().clearAllCaches(); } final String serverId = theRequest.getServerIdWithDefault(myConfig); final String serverBase = theRequest.getServerBase(theServletRequest, myConfig); final String serverName = theRequest.getServerName(myConfig); theModel.put("serverId", serverId); theModel.put("base", serverBase); theModel.put("baseName", serverName); theModel.put("resourceName", defaultString(theRequest.getResource())); theModel.put("encoding", theRequest.getEncoding()); theModel.put("pretty", theRequest.getPretty()); theModel.put("_summary", theRequest.get_summary()); theModel.put("serverEntries", myConfig.getIdToServerName()); return loadAndAddConf(theServletRequest, theRequest, theModel); }
@Override public int read(final CharBuffer target) throws IOException { if (readerLogger.isTraceEnabled()) { readerLogger.trace( "[THYMELEAF][TEMPLATEPREPROCESSINGREADER][{}] CALLING read(CharBuffer). Will be delegated as several calls to read(char[], 0, 1024).", new Object[] {TemplateEngine.threadIndex()}); } final char[] cbuf = new char[1024]; int totalRead = -1; int read; while ((read = read(cbuf, 0, cbuf.length)) != -1) { target.put(cbuf, 0, read); if (totalRead == -1) { totalRead = 0; } totalRead += read; } return totalRead; }
@Override public int read(char[] cbuf, int off, int len) throws IOException { if (readerLogger.isTraceEnabled()) { readerLogger.trace( "[THYMELEAF][TEMPLATEPREPROCESSINGREADER][{}] CALLING read(char[], {}, {})", new Object[] {TemplateEngine.threadIndex(), Integer.valueOf(off), Integer.valueOf(len)}); } if ((len * 2) > this.overflow.length) { // Resize buffer and overflow this.buffer = new char[len + 1024]; final char[] newOverflow = new char[len + 2048]; System.arraycopy(this.overflow, 0, newOverflow, 0, this.overflowIndex); this.overflow = newOverflow; } int bufferSize = 0; if (this.overflowIndex > 0) { final int copied = copyToResult(this.overflow, 0, this.overflowIndex, this.buffer, 0, this.buffer.length); bufferSize += copied; if (readerLogger.isTraceEnabled()) { readerLogger.trace( "[THYMELEAF][TEMPLATEPREPROCESSINGREADER][{}] READ FROM OVERFLOW BUFFER {} Some content from the overflow buffer has been copied into results.", new Object[] {TemplateEngine.threadIndex(), Integer.valueOf(copied)}); } } char[] overflowOverflow = null; if (this.overflowIndex > 0) { // Overflow did not entirely fit into buffer, and some overflow // had to be relocated. This overflow will have to be placed at the end of the // overflow generated in the current call (if any). overflowOverflow = new char[this.overflowIndex]; System.arraycopy(this.overflow, 0, overflowOverflow, 0, this.overflowIndex); if (readerLogger.isTraceEnabled()) { readerLogger.trace( "[THYMELEAF][TEMPLATEPREPROCESSINGREADER][{}] RELLOCATED SOME OVERFLOW CONTENTS, WAITING TO BE ADDED TO RESULT/NEW OVERFLOW {} Some content was remaining at the overflow buffer and will have to be rellocated.", new Object[] {TemplateEngine.threadIndex(), Integer.valueOf(this.overflowIndex)}); } this.overflowIndex = 0; } if (!this.noMoreToRead && bufferSize < this.buffer.length) { // Buffer was not filled up with content from overflow, so ask for more content final int toBeRead = this.buffer.length - bufferSize; final int reallyRead = this.bufferedReader.read(this.buffer, bufferSize, toBeRead); if (readerLogger.isTraceEnabled()) { readerLogger.trace( "[THYMELEAF][TEMPLATEPREPROCESSINGREADER][{}] READ FROM SOURCE {} A read operation was executed on the source reader (max chars requested: {}).", new Object[] { TemplateEngine.threadIndex(), Integer.valueOf(reallyRead), Integer.valueOf(toBeRead) }); } if (reallyRead < 0) { if (bufferSize == 0) { if (readerLogger.isTraceEnabled()) { readerLogger.trace( "[THYMELEAF][TEMPLATEPREPROCESSINGREADER][{}] RETURN {} After trying to read from input: No input left, no buffer left.", new Object[] {TemplateEngine.threadIndex(), Integer.valueOf(reallyRead)}); } return reallyRead; } this.noMoreToRead = true; } else { bufferSize += reallyRead; } } if (this.noMoreToRead && bufferSize == 0) { // Nothing left to do. Just return -1 if (readerLogger.isTraceEnabled()) { readerLogger.trace( "[THYMELEAF][TEMPLATEPREPROCESSINGREADER][{}] RETURN -1 Reader was already marked to be finished. No more input, no more buffer.", new Object[] {TemplateEngine.threadIndex()}); } return -1; } int totalRead = 0; int cbufi = off; int last = off + len; int buffi = 0; while (cbufi < last && buffi < bufferSize) { /* * Process DOCTYPE first (if needed) */ if (!this.docTypeClauseRead) { final int matchedDocType = match(DOCTYPE, 0, DOCTYPE.length, this.buffer, buffi, bufferSize); if (matchedDocType > 0) { this.docTypeClause = new String(this.buffer, buffi, matchedDocType); this.docTypeClauseRead = true; final char[] normalizedDocType = normalizeDocTypeClause(this.buffer, buffi, matchedDocType); final int copied = copyToResult(normalizedDocType, 0, matchedDocType, cbuf, cbufi, last); cbufi += copied; totalRead += copied; buffi += matchedDocType; continue; } } final int matchedStartOfComment = (this.inComment ? -2 : match(COMMENT_START, 0, COMMENT_START.length, this.buffer, buffi, bufferSize)); final int matchedEndOfComment = (this.inComment ? match(COMMENT_END, 0, COMMENT_END.length, this.buffer, buffi, bufferSize) : -2); final int matchedEntity = (this.inComment ? -2 : match(ENTITY, 0, ENTITY.length, this.buffer, buffi, bufferSize)); if (matchedStartOfComment > 0) { this.inComment = true; final int copied = copyToResult(this.buffer, buffi, matchedStartOfComment, cbuf, cbufi, last); cbufi += copied; totalRead += copied; buffi += matchedStartOfComment; continue; } if (matchedEndOfComment > 0) { this.inComment = false; final int copied = copyToResult(this.buffer, buffi, matchedEndOfComment, cbuf, cbufi, last); cbufi += copied; totalRead += copied; buffi += matchedEndOfComment; continue; } if (matchedEntity > 0) { final int copied = copyToResult( ENTITY_START_SUBSTITUTE_CHAR_ARRAY, 0, ENTITY_START_SUBSTITUTE_CHAR_ARRAY.length, cbuf, cbufi, last); cbufi += copied; totalRead += copied; buffi += 1; // Only one character is substituted (&) continue; } cbuf[cbufi++] = this.buffer[buffi++]; totalRead++; } if (buffi < bufferSize) { // Copy remaining buffer to overflow final int toBeOverFlowed = bufferSize - buffi; final int copied = copyToResult(this.buffer, buffi, toBeOverFlowed, cbuf, cbufi, last); // copied must be zero if (copied != 0) { throw new TemplateInputException("Overflow was not correctly computed!"); } } if (overflowOverflow != null) { final int copied = copyToResult(overflowOverflow, 0, overflowOverflow.length, cbuf, cbufi, last); // copied must be zero if (copied != 0) { throw new TemplateInputException("Overflow-overflow was not correctly computed!"); } } if (readerLogger.isTraceEnabled()) { final char[] result = new char[totalRead]; System.arraycopy(cbuf, off, result, 0, totalRead); readerLogger.trace( "[THYMELEAF][TEMPLATEPREPROCESSINGREADER][{}] RETURN {} Input was read and processed. Returning content: [[{}]]", new Object[] { TemplateEngine.threadIndex(), Integer.valueOf(totalRead), new String(result) }); } return totalRead; }