All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.apache.camel.component.thymeleaf.ThymeleafEndpoint Maven / Gradle / Ivy

There is a newer version: 4.8.1
Show newest version
/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.camel.component.thymeleaf;

import java.util.Map;

import org.apache.camel.Category;
import org.apache.camel.Component;
import org.apache.camel.Exchange;
import org.apache.camel.ExchangePattern;
import org.apache.camel.RuntimeCamelException;
import org.apache.camel.component.ResourceEndpoint;
import org.apache.camel.spi.UriEndpoint;
import org.apache.camel.spi.UriParam;
import org.apache.camel.support.ExchangeHelper;
import org.apache.camel.util.ObjectHelper;
import org.thymeleaf.TemplateEngine;
import org.thymeleaf.context.Context;
import org.thymeleaf.templateresolver.ClassLoaderTemplateResolver;
import org.thymeleaf.templateresolver.DefaultTemplateResolver;
import org.thymeleaf.templateresolver.FileTemplateResolver;
import org.thymeleaf.templateresolver.ITemplateResolver;
import org.thymeleaf.templateresolver.StringTemplateResolver;
import org.thymeleaf.templateresolver.UrlTemplateResolver;
import org.thymeleaf.templateresolver.WebApplicationTemplateResolver;
import org.thymeleaf.web.servlet.JakartaServletWebApplication;

/**
 * Transform messages using a Thymeleaf template.
 */
@UriEndpoint(firstVersion = "4.1.0", scheme = "thymeleaf", title = "Thymeleaf", syntax = "thymeleaf:resourceUri",
             producerOnly = true, category = { Category.TRANSFORMATION }, headersClass = ThymeleafConstants.class)
public class ThymeleafEndpoint extends ResourceEndpoint {

    private TemplateEngine templateEngine;

    private String template;

    private JakartaServletWebApplication jakartaServletWebApplication;

    @UriParam(defaultValue = "CLASS_LOADER", description = "The type of resolver to be used by the template engine.",
              javaType = "org.apache.camel.component.thymeleaf.ThymeleafResolverType")
    private ThymeleafResolverType resolver = ThymeleafResolverType.CLASS_LOADER;

    @UriParam(description = "The template mode to be applied to templates.")
    private String templateMode;

    @UriParam(description = "An optional prefix added to template names to convert them into resource names.")
    private String prefix;

    @UriParam(description = "An optional suffix added to template names to convert them into resource names.")
    private String suffix;

    @UriParam(description = "The character encoding to be used for reading template resources.")
    private String encoding;

    @UriParam(description = "The order in which this template will be resolved as part of the resolver chain.")
    private Integer order;

    @UriParam(description = "Whether a template resources will be checked for existence before being returned.")
    private Boolean checkExistence;

    @UriParam(description = "The cache Time To Live for templates, expressed in milliseconds.")
    private Long cacheTimeToLive;

    @UriParam(description = "Whether templates have to be considered cacheable or not.")
    private Boolean cacheable;

    public ThymeleafEndpoint() {

    }

    public ThymeleafEndpoint(String endpointURI, Component component, String resourceURI) {

        super(endpointURI, component, resourceURI);
    }

    @Override
    public ExchangePattern getExchangePattern() {

        return ExchangePattern.InOut;
    }

    @Override
    protected String createEndpointUri() {

        return "thymeleaf:" + getResourceUri();
    }

    public String getTemplateMode() {

        return templateMode;
    }

    /**
     * 

* Sets the template mode to be applied to templates resolved by this endpoint. *

*

* One of {@code HTML}, {@code XML}, {@code TEXT}, {@code JAVASCRIPT}, {@code CSS}, {@code RAW}. *

*

* Note that this template mode will be ignored if the template resource name ends in a known file name suffix: * {@code .html}, {@code .htm}, {@code .xhtml}, {@code .xml}, {@code .js}, {@code .json}, {@code .css}, * {@code .rss}, {@code .atom}, {@code .txt}. *

* * @param templateMode the template mode. */ public void setTemplateMode(String templateMode) { this.templateMode = templateMode; } public ThymeleafResolverType getResolver() { return resolver; } /** * Sets the type of resolver to be used by the template engine. *

* One of {@code CLASS_LOADER}, {@code DEFAULT}, {@code FILE}, {@code STRING}, {@code URL}, {@code WEB_APP}. *

*/ public void setResolver(ThymeleafResolverType resolver) { this.resolver = resolver; } public String getPrefix() { return prefix; } /** *

* Sets a new (optional) prefix to be added to all template names in order to convert template names into * resource names. *

* * @param prefix the prefix to be set. */ public void setPrefix(String prefix) { this.prefix = prefix; } public String getSuffix() { return suffix; } /** *

* Sets a new (optional) suffix to be added to all template names in order to convert template names into * resource names. *

*

* Note that this suffix may not be applied to the template name if the template name already ends in a known file * name suffix: {@code .html}, {@code .htm}, {@code .xhtml}, {@code .xml}, {@code .js}, {@code .json}, {@code .css}, * {@code .rss}, {@code .atom}, {@code .txt}. *

* * @param suffix the suffix to be set. */ public void setSuffix(String suffix) { this.suffix = suffix; } public String getEncoding() { return encoding; } /** *

* Sets a new character encoding for reading template resources. *

* * @param encoding the character encoding to be used. */ public void setEncoding(String encoding) { this.encoding = encoding; } public Integer getOrder() { return order; } /** *

* Sets a new order for the template engine in the chain. Order should start with 1. *

* * @param order the new order. */ public void setOrder(Integer order) { this.order = order; } public Boolean getCheckExistence() { return checkExistence; } /** *

* Sets whether template resources will be checked for existence before being returned or not. *

*

* Default value is {@code FALSE}. *

* * @param checkExistence {@code true} if resource existence should be checked, {@code false} if not */ public void setCheckExistence(Boolean checkExistence) { this.checkExistence = checkExistence; } public Long getCacheTimeToLive() { return cacheTimeToLive; } /** *

* Sets a new value for the cache TTL for resolved templates. *

*

* If a template is resolved as cacheable but cache TTL is null, this means the template will live in cache * until evicted by LRU (Least Recently Used) algorithm for being the oldest entry in cache. *

* * @param cacheTimeToLive the new cache TTL in milliseconds, or null for using natural LRU eviction. */ public void setCacheTimeToLive(Long cacheTimeToLive) { this.cacheTimeToLive = cacheTimeToLive; } public Boolean getCacheable() { return cacheable; } /** *

* Sets a new value for the cacheable flag. *

* * @param cacheable whether resolved patterns should be considered cacheable or not. */ public void setCacheable(Boolean cacheable) { this.cacheable = cacheable; } protected synchronized TemplateEngine getTemplateEngine() { if (templateEngine == null) { ITemplateResolver templateResolver; switch (resolver) { case CLASS_LOADER -> { templateResolver = classLoaderTemplateResolver(); } case DEFAULT -> { templateResolver = defaultTemplateResolver(); } case FILE -> { templateResolver = fileTemplateResolver(); } case STRING -> { templateResolver = stringTemplateResolver(); } case URL -> { templateResolver = urlTemplateResolver(); } case WEB_APP -> { templateResolver = webApplicationTemplateResolver(); } default -> { throw new RuntimeCamelException("cannot determine TemplateResolver for type " + resolver); } } templateEngine = new TemplateEngine(); templateEngine.setTemplateResolver(templateResolver); } return templateEngine; } /** * To use the {@link TemplateEngine} otherwise a new engine is created */ public void setTemplateEngine(TemplateEngine templateEngine) { this.templateEngine = templateEngine; } public void setJakartaServletWebApplication(JakartaServletWebApplication jakartaServletWebApplication) { this.jakartaServletWebApplication = jakartaServletWebApplication; } public void setTemplate(String template) { this.template = template; } @Override public void clearContentCache() { if (templateEngine != null) { templateEngine.clearTemplateCache(); } } public ThymeleafEndpoint findOrCreateEndpoint(String uri, String newResourceUri) { String newUri = uri.replace(getResourceUri(), newResourceUri); log.debug("Getting endpoint with URI: {}", newUri); return getCamelContext().getEndpoint(newUri, ThymeleafEndpoint.class); } @Override protected void onExchange(Exchange exchange) throws Exception { String path = getResourceUri(); ObjectHelper.notNull(path, "resourceUri"); String newResourceUri = exchange.getIn().getHeader(ThymeleafConstants.THYMELEAF_RESOURCE_URI, String.class); if (newResourceUri != null) { // remove the header so that it is not propagated in the exchange exchange.getIn().removeHeader(ThymeleafConstants.THYMELEAF_RESOURCE_URI); log.debug("{} set to {}, creating new endpoint to handle exchange", ThymeleafConstants.THYMELEAF_RESOURCE_URI, newResourceUri); try (ThymeleafEndpoint newEndpoint = findOrCreateEndpoint(getEndpointUri(), newResourceUri)) { newEndpoint.onExchange(exchange); } return; } String template = exchange.getIn().getHeader(ThymeleafConstants.THYMELEAF_TEMPLATE, String.class); if (template != null) { this.template = template; // remove the header so that it is not propagated in the exchange exchange.getIn().removeHeader(ThymeleafConstants.THYMELEAF_TEMPLATE); } else { this.template = path; } @SuppressWarnings("unchecked") Map dataModel = exchange.getIn().getHeader(ThymeleafConstants.THYMELEAF_VARIABLE_MAP, Map.class); if (dataModel == null) { dataModel = ExchangeHelper.createVariableMap(exchange, isAllowContextMapAll()); } else { ExchangeHelper.populateVariableMap(exchange, dataModel, isAllowContextMapAll()); // remove the header so that it is not propagated in the exchange exchange.getIn().removeHeader(ThymeleafConstants.THYMELEAF_VARIABLE_MAP); } // let thymeleaf parse and generate the result TemplateEngine templateEngine = getTemplateEngine(); Context context = new Context(); context.setVariables(dataModel); String buffer = templateEngine.process(this.template, context); // store the result in the exchange body ExchangeHelper.setInOutBodyPatternAware(exchange, buffer); } private ITemplateResolver classLoaderTemplateResolver() { ClassLoaderTemplateResolver resolver = new ClassLoaderTemplateResolver(); if (cacheable != null) { resolver.setCacheable(cacheable); } if (cacheTimeToLive != null) { resolver.setCacheTTLMs(cacheTimeToLive); } if (encoding != null) { resolver.setCharacterEncoding(encoding); } if (checkExistence != null) { resolver.setCheckExistence(checkExistence); } if (order != null) { resolver.setOrder(order); } if (prefix != null) { resolver.setPrefix(prefix); } if (suffix != null) { resolver.setSuffix(suffix); } if (templateMode != null) { resolver.setTemplateMode(templateMode); } if (template == null) { throw new RuntimeCamelException("template must be provided"); } return resolver; } private ITemplateResolver defaultTemplateResolver() { DefaultTemplateResolver resolver = new DefaultTemplateResolver(); if (checkExistence != null) { resolver.setCheckExistence(checkExistence); } if (order != null) { resolver.setOrder(order); } if (templateMode != null) { resolver.setTemplateMode(templateMode); } if (template == null) { throw new RuntimeCamelException("template must be provided"); } else { resolver.setTemplate(template); } return resolver; } private ITemplateResolver fileTemplateResolver() { FileTemplateResolver resolver = new FileTemplateResolver(); if (cacheable != null) { resolver.setCacheable(cacheable); } if (cacheTimeToLive != null) { resolver.setCacheTTLMs(cacheTimeToLive); } if (encoding != null) { resolver.setCharacterEncoding(encoding); } if (checkExistence != null) { resolver.setCheckExistence(checkExistence); } if (order != null) { resolver.setOrder(order); } if (prefix != null) { resolver.setPrefix(prefix); } if (suffix != null) { resolver.setSuffix(suffix); } if (templateMode != null) { resolver.setTemplateMode(templateMode); } if (template == null) { throw new RuntimeCamelException("template must be provided"); } return resolver; } private ITemplateResolver stringTemplateResolver() { StringTemplateResolver resolver = new StringTemplateResolver(); if (cacheable != null) { resolver.setCacheable(cacheable); } if (cacheTimeToLive != null) { resolver.setCacheTTLMs(cacheTimeToLive); } if (checkExistence != null) { resolver.setCheckExistence(checkExistence); } if (order != null) { resolver.setOrder(order); } if (templateMode != null) { resolver.setTemplateMode(templateMode); } if (template == null) { throw new RuntimeCamelException("template must be provided"); } return resolver; } private ITemplateResolver urlTemplateResolver() { UrlTemplateResolver resolver = new UrlTemplateResolver(); if (cacheable != null) { resolver.setCacheable(cacheable); } if (cacheTimeToLive != null) { resolver.setCacheTTLMs(cacheTimeToLive); } if (encoding != null) { resolver.setCharacterEncoding(encoding); } if (order != null) { resolver.setOrder(order); } if (prefix != null) { resolver.setPrefix(prefix); } if (suffix != null) { resolver.setSuffix(suffix); } if (templateMode != null) { resolver.setTemplateMode(templateMode); } if (template == null) { throw new RuntimeCamelException("template must be provided"); } return resolver; } private ITemplateResolver webApplicationTemplateResolver() { WebApplicationTemplateResolver resolver = new WebApplicationTemplateResolver(jakartaServletWebApplication); if (cacheable != null) { resolver.setCacheable(cacheable); } if (cacheTimeToLive != null) { resolver.setCacheTTLMs(cacheTimeToLive); } if (encoding != null) { resolver.setCharacterEncoding(encoding); } if (checkExistence != null) { resolver.setCheckExistence(checkExistence); } if (order != null) { resolver.setOrder(order); } if (prefix != null) { resolver.setPrefix(prefix); } if (suffix != null) { resolver.setSuffix(suffix); } if (templateMode != null) { resolver.setTemplateMode(templateMode); } if (template == null) { throw new RuntimeCamelException("template must be provided"); } return resolver; } }




© 2015 - 2025 Weber Informatics LLC | Privacy Policy