Example #1
0
 /** {@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();
   }
 }
Example #9
0
  @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 () {");
  }
Example #11
0
  @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;
  }
Example #12
0
  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;
  }
Example #13
0
 /** {@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);
   }
 }
Example #14
0
  @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);
   }
 }
Example #17
0
  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 />";
    }
  }
Example #18
0
 @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;
  }