use of org.thymeleaf.cache.TemplateCacheKey in project sling by apache.
the class TemplateManager method clearCachesFor.
/**
* <p>
* Clears any existing entries for template of the specified
* name at the template cache.
* </p>
*
* @param template the name of the template whose entries have to be cleared.
*/
public void clearCachesFor(final String template) {
Validate.notNull(template, "Cannot specify null template");
if (this.templateCache != null) {
final Set<TemplateCacheKey> keysToBeRemoved = new HashSet<TemplateCacheKey>(4);
final Set<TemplateCacheKey> templateCacheKeys = this.templateCache.keySet();
// to the original cache store and we provoke ConcurrentModificationExceptions when removing entries
for (final TemplateCacheKey templateCacheKey : templateCacheKeys) {
final String ownerTemplate = templateCacheKey.getOwnerTemplate();
if (ownerTemplate != null) {
// It's not a standalone template, so we are interested on the owner template
if (ownerTemplate.equals(template)) {
keysToBeRemoved.add(templateCacheKey);
}
} else {
if (templateCacheKey.getTemplate().equals(template)) {
keysToBeRemoved.add(templateCacheKey);
}
}
}
for (final TemplateCacheKey keyToBeRemoved : keysToBeRemoved) {
this.templateCache.clearKey(keyToBeRemoved);
}
}
}
use of org.thymeleaf.cache.TemplateCacheKey in project sling by apache.
the class TemplateManager method parseStandalone.
/*
* -------------
* PARSE methods
* -------------
*
* Parse methods will create 'template models' that are basically collections of events in the form of an
* immutable IModel implementation.
*/
public TemplateModel parseStandalone(final ITemplateContext context, final String template, final Set<String> templateSelectors, final TemplateMode templateMode, final boolean useCache, final boolean failIfNotExists) {
Validate.notNull(context, "Context cannot be null");
Validate.notNull(template, "Template cannot be null");
// templateSelectors CAN be null if we are going to render the entire template
// templateMode CAN be null if we are going to use the mode specified by the template resolver
// templateResolutionAttributes CAN be null
final String ownerTemplate = context.getTemplateData().getTemplate();
final Map<String, Object> templateResolutionAttributes = context.getTemplateResolutionAttributes();
final Set<String> cleanTemplateSelectors;
if (templateSelectors != null && !templateSelectors.isEmpty()) {
Validate.containsNoEmpties(templateSelectors, "If specified, the Template Selector set cannot contain any nulls or empties");
if (templateSelectors.size() == 1) {
cleanTemplateSelectors = Collections.singleton(templateSelectors.iterator().next());
} else {
// We will be using a TreeSet because we want the selectors to be ORDERED, so that comparison at the
// equals(...) method works alright
cleanTemplateSelectors = Collections.unmodifiableSet(new TreeSet<String>(templateSelectors));
}
} else {
cleanTemplateSelectors = null;
}
final TemplateCacheKey cacheKey = useCache ? new TemplateCacheKey(ownerTemplate, template, cleanTemplateSelectors, 0, 0, templateMode, templateResolutionAttributes) : null;
/*
* First look at the cache - it might be already cached
*/
if (useCache && this.templateCache != null) {
final TemplateModel cached = this.templateCache.get(cacheKey);
if (cached != null) {
/*
* Just at the end, and importantly AFTER CACHING, check if we need to apply any pre-processors
* to this model before returning and letting the engine insert the model in any way it needs.
*/
return applyPreProcessorsIfNeeded(context, cached);
}
}
/*
* Resolve the template
*/
final TemplateResolution templateResolution = resolveTemplate(this.configuration, context, ownerTemplate, template, templateResolutionAttributes, failIfNotExists);
/*
* Once the template has been resolved (or tried to), and depending on the value of our 'failIfNotExists'
* flag, we will check two conditions in which we will be returning null:
*
* 1. No template resolver has been able to resolve the template (this can happen if resolvers are
* configured with the 'checkExistence' flag to true).
* 2. If the template was resolved, its existence should be checked in order to avoid exceptions during
* the reading phase.
*
* NOTE we will not cache this "null" result because the fact that a template is cacheable or not is
* determined by template resolvers. And in this case there is no template resolver being applied
* (actually, we are here because no resolver had success).
*/
if (!failIfNotExists) {
if (templateResolution == null) {
// No resolver could resolve this
return null;
}
if (!templateResolution.isTemplateResourceExistenceVerified()) {
final ITemplateResource resource = templateResolution.getTemplateResource();
if (resource == null || !resource.exists()) {
// has not been cached (e.g. when it does not exist)
return null;
}
}
}
/*
* Build the TemplateData object
*/
final TemplateData templateData = buildTemplateData(templateResolution, template, cleanTemplateSelectors, templateMode, useCache);
/*
* Create the Template Handler that will be in charge of building the TemplateModel
*/
final ModelBuilderTemplateHandler builderHandler = new ModelBuilderTemplateHandler(this.configuration, templateData);
/*
* PROCESS THE TEMPLATE
*/
final ITemplateParser parser = getParserForTemplateMode(templateData.getTemplateMode());
parser.parseStandalone(this.configuration, ownerTemplate, template, cleanTemplateSelectors, templateData.getTemplateResource(), templateData.getTemplateMode(), templateResolution.getUseDecoupledLogic(), builderHandler);
final TemplateModel templateModel = builderHandler.getModel();
/*
* Cache the template if it is cacheable
*/
if (useCache && this.templateCache != null) {
if (templateResolution.getValidity().isCacheable()) {
this.templateCache.put(cacheKey, templateModel);
}
}
/*
* Last step: just at the end, and importantly AFTER CACHING, check if we need to apply any pre-processors
* to this model before returning and letting the engine insert the model in any way it needs.
*/
return applyPreProcessorsIfNeeded(context, templateModel);
}
use of org.thymeleaf.cache.TemplateCacheKey in project sling by apache.
the class TemplateManager method parseAndProcess.
/*
* -------------------------
* PARSE-AND-PROCESS methods
* -------------------------
*
* These methods perform the whole cycle of a template's processing: resolving, parsing and processing.
* This is only meant to be called from the TemplateEngine
*/
public void parseAndProcess(final TemplateSpec templateSpec, final IContext context, final Writer writer) {
Validate.notNull(templateSpec, "Template Specification cannot be null");
Validate.notNull(context, "Context cannot be null");
Validate.notNull(writer, "Writer cannot be null");
// TemplateSpec will already have validated its contents, so need to do it here (template selectors,
// resolution attributes, etc.)
final String template = templateSpec.getTemplate();
final Set<String> templateSelectors = templateSpec.getTemplateSelectors();
final TemplateMode templateMode = templateSpec.getTemplateMode();
final Map<String, Object> templateResolutionAttributes = templateSpec.getTemplateResolutionAttributes();
final TemplateCacheKey cacheKey = new TemplateCacheKey(// ownerTemplate
null, template, templateSelectors, // lineOffset, colOffset
0, // lineOffset, colOffset
0, templateMode, templateResolutionAttributes);
/*
* First look at the cache - it might be already cached
*/
if (this.templateCache != null) {
final TemplateModel cached = this.templateCache.get(cacheKey);
if (cached != null) {
final IEngineContext engineContext = EngineContextManager.prepareEngineContext(this.configuration, cached.getTemplateData(), templateResolutionAttributes, context);
/*
* Create the handler chain to process the data.
* This is PARSE + PROCESS, so its called from the TemplateEngine, and the only case in which we should apply
* both pre-processors and post-processors (besides creating a last output-to-writer step)
*/
final ProcessorTemplateHandler processorTemplateHandler = new ProcessorTemplateHandler();
final ITemplateHandler processingHandlerChain = createTemplateProcessingHandlerChain(engineContext, true, true, processorTemplateHandler, writer);
cached.process(processingHandlerChain);
EngineContextManager.disposeEngineContext(engineContext);
return;
}
}
/*
* Resolve the template
*/
final TemplateResolution templateResolution = resolveTemplate(this.configuration, context, null, template, templateResolutionAttributes, true);
/*
* Build the TemplateData object
*/
final TemplateData templateData = buildTemplateData(templateResolution, template, templateSelectors, templateMode, true);
/*
* Prepare the context instance that corresponds to this execution of the template engine
*/
final IEngineContext engineContext = EngineContextManager.prepareEngineContext(this.configuration, templateData, templateResolutionAttributes, context);
/*
* Create the handler chain to process the data.
* This is PARSE + PROCESS, so its called from the TemplateEngine, and the only case in which we should apply
* both pre-processors and post-processors (besides creating a last output-to-writer step)
*/
final ProcessorTemplateHandler processorTemplateHandler = new ProcessorTemplateHandler();
final ITemplateHandler processingHandlerChain = createTemplateProcessingHandlerChain(engineContext, true, true, processorTemplateHandler, writer);
/*
* Obtain the parser
*/
final ITemplateParser parser = getParserForTemplateMode(engineContext.getTemplateMode());
/*
* If the resolved template is cacheable, so we will first read it as an object, cache it, and then process it
*/
if (templateResolution.getValidity().isCacheable() && this.templateCache != null) {
// Create the handler chain to create the Template object
final ModelBuilderTemplateHandler builderHandler = new ModelBuilderTemplateHandler(this.configuration, templateData);
// Process the template into a TemplateModel
parser.parseStandalone(this.configuration, null, template, templateSelectors, templateData.getTemplateResource(), engineContext.getTemplateMode(), templateResolution.getUseDecoupledLogic(), builderHandler);
// Obtain the TemplateModel
final TemplateModel templateModel = builderHandler.getModel();
// Put the new template into cache
this.templateCache.put(cacheKey, templateModel);
// Process the read (+cached) template itself
templateModel.process(processingHandlerChain);
} else {
// Process the template, which is not cacheable (so no worry about caching)
parser.parseStandalone(this.configuration, null, template, templateSelectors, templateData.getTemplateResource(), engineContext.getTemplateMode(), templateResolution.getUseDecoupledLogic(), processingHandlerChain);
}
/*
* Dispose the engine context now that processing has been done
*/
EngineContextManager.disposeEngineContext(engineContext);
}
use of org.thymeleaf.cache.TemplateCacheKey in project sling by apache.
the class TemplateManager method parseString.
public TemplateModel parseString(final TemplateData ownerTemplateData, final String template, final int lineOffset, final int colOffset, final TemplateMode templateMode, final boolean useCache) {
Validate.notNull(ownerTemplateData, "Owner template cannot be null");
Validate.notNull(template, "Template cannot be null");
// NOTE selectors cannot be specified when parsing a nested template
// templateMode CAN be null (if we are using the owner's)
final String ownerTemplate = ownerTemplateData.getTemplate();
final TemplateMode definitiveTemplateMode = (templateMode != null ? templateMode : ownerTemplateData.getTemplateMode());
final TemplateCacheKey cacheKey = useCache ? new TemplateCacheKey(ownerTemplate, template, null, lineOffset, colOffset, definitiveTemplateMode, // template resolution attributes do not affect string fragments: no resolution!
null) : null;
/*
* First look at the cache - it might be already cached
*/
if (useCache && this.templateCache != null) {
final TemplateModel cached = this.templateCache.get(cacheKey);
if (cached != null) {
return cached;
}
}
/*
* Compute the cache validity. In order for a String fragment to be cacheable, we will have to have
* specified the 'useCache' parameter as true, and the owner template must be cacheable
*/
final ICacheEntryValidity cacheValidity = (useCache && ownerTemplateData.getValidity().isCacheable() ? AlwaysValidCacheEntryValidity.INSTANCE : NonCacheableCacheEntryValidity.INSTANCE);
/*
* Build the TemplateData
*
* NOTE how, by default, we are using the owner's TemplateData. And even if the template mode changes
* and we need to create a new TemplateData object, we will keep the original name and resource.
* This is because we want the elements inside the fragment to me reported as belonging to the
* container template, not to the fragment String considered as a fragment in its own (which
* wouldn't make sense)
*/
final TemplateData templateData = (templateMode == null ? // No change in Template Mode -> simply use the owner's template data
ownerTemplateData : // Template Mode changed -> new TemplateData, very similar but different template mode
new TemplateData(ownerTemplateData.getTemplate(), ownerTemplateData.getTemplateSelectors(), ownerTemplateData.getTemplateResource(), templateMode, cacheValidity));
/*
* Create the Template Handler that will be in charge of building the TemplateModel
*
* NOTE how we are using the owner's TemplateData and not a new one created for this fragment, because
* we want the elements inside the fragment to me reported as belonging to the container template,
* not to the fragment String considered as a fragment in its own (which wouldn't make sense)
*/
final ModelBuilderTemplateHandler builderHandler = new ModelBuilderTemplateHandler(this.configuration, templateData);
/*
* PROCESS THE TEMPLATE
*/
final ITemplateParser parser = getParserForTemplateMode(templateData.getTemplateMode());
// NO RESOURCE is sent to the parser, in this case. We simply pass the String template
parser.parseString(this.configuration, ownerTemplate, template, lineOffset, colOffset, definitiveTemplateMode, builderHandler);
final TemplateModel parsedTemplate = builderHandler.getModel();
/*
* Cache the template if it is cacheable
*/
if (useCache && this.templateCache != null) {
if (cacheValidity.isCacheable()) {
this.templateCache.put(cacheKey, parsedTemplate);
}
}
return parsedTemplate;
}
use of org.thymeleaf.cache.TemplateCacheKey in project sling by apache.
the class TemplateManager method parseAndProcessThrottled.
public ThrottledTemplateProcessor parseAndProcessThrottled(final TemplateSpec templateSpec, final IContext context) {
Validate.notNull(templateSpec, "Template Specification cannot be null");
Validate.notNull(context, "Context cannot be null");
// TemplateSpec will already have validated its contents, so need to do it here (template selectors,
// resolution attributes, etc.)
final String template = templateSpec.getTemplate();
final Set<String> templateSelectors = templateSpec.getTemplateSelectors();
final TemplateMode templateMode = templateSpec.getTemplateMode();
final Map<String, Object> templateResolutionAttributes = templateSpec.getTemplateResolutionAttributes();
final TemplateCacheKey cacheKey = new TemplateCacheKey(// ownerTemplate
null, template, templateSelectors, // lineOffset, colOffset
0, // lineOffset, colOffset
0, templateMode, templateResolutionAttributes);
/*
* Instantiate the throttling artifacts
*/
final TemplateFlowController flowController = new TemplateFlowController();
final ThrottledTemplateWriter throttledTemplateWriter = new ThrottledTemplateWriter(template, flowController);
/*
* First look at the cache - it might be already cached
*/
if (this.templateCache != null) {
final TemplateModel cached = this.templateCache.get(cacheKey);
if (cached != null) {
final IEngineContext engineContext = EngineContextManager.prepareEngineContext(this.configuration, cached.getTemplateData(), templateResolutionAttributes, context);
/*
* Create the handler chain to process the data.
* This is PARSE + PROCESS, so its called from the TemplateEngine, and the only case in which we should apply
* both pre-processors and post-processors (besides creating a last output-to-writer step)
*/
final ProcessorTemplateHandler processorTemplateHandler = new ProcessorTemplateHandler();
processorTemplateHandler.setFlowController(flowController);
final ITemplateHandler processingHandlerChain = createTemplateProcessingHandlerChain(engineContext, true, true, processorTemplateHandler, throttledTemplateWriter);
/*
* Return the throttled template processor
*/
return new ThrottledTemplateProcessor(templateSpec, engineContext, cached, processingHandlerChain, processorTemplateHandler, flowController, throttledTemplateWriter);
}
}
/*
* Resolve the template
*/
final TemplateResolution templateResolution = resolveTemplate(this.configuration, context, null, template, templateResolutionAttributes, true);
/*
* Build the TemplateData object
*/
final TemplateData templateData = buildTemplateData(templateResolution, template, templateSelectors, templateMode, true);
/*
* Prepare the context instance that corresponds to this execution of the template engine
*/
final IEngineContext engineContext = EngineContextManager.prepareEngineContext(this.configuration, templateData, templateResolutionAttributes, context);
/*
* Create the handler chain to process the data.
* This is PARSE + PROCESS, so its called from the TemplateEngine, and the only case in which we should apply
* both pre-processors and post-processors (besides creating a last output-to-writer step)
*/
final ProcessorTemplateHandler processorTemplateHandler = new ProcessorTemplateHandler();
processorTemplateHandler.setFlowController(flowController);
final ITemplateHandler processingHandlerChain = createTemplateProcessingHandlerChain(engineContext, true, true, processorTemplateHandler, throttledTemplateWriter);
/*
* Obtain the parser
*/
final ITemplateParser parser = getParserForTemplateMode(engineContext.getTemplateMode());
/*
* Parse the template into a TemplateModel. Even if we are not using the cache, throttled template processings
* will always be processed first into a TemplateModel, so that throttling can then be applied on an
* already-in-memory sequence of events
*/
final ModelBuilderTemplateHandler builderHandler = new ModelBuilderTemplateHandler(this.configuration, templateData);
parser.parseStandalone(this.configuration, null, template, templateSelectors, templateData.getTemplateResource(), engineContext.getTemplateMode(), templateResolution.getUseDecoupledLogic(), builderHandler);
final TemplateModel templateModel = builderHandler.getModel();
/*
* If cache is active, put the cached TemplateModel into cache
*/
if (templateResolution.getValidity().isCacheable() && this.templateCache != null) {
// Put the new template into cache
this.templateCache.put(cacheKey, templateModel);
}
/*
* Return the throttled template processor
*/
return new ThrottledTemplateProcessor(templateSpec, engineContext, templateModel, processingHandlerChain, processorTemplateHandler, flowController, throttledTemplateWriter);
}
Aggregations