This is an automated email from the ASF dual-hosted git repository. rombert pushed a commit to annotated tag org.apache.sling.scripting.thymeleaf-1.0.0 in repository https://gitbox.apache.org/repos/asf/sling-org-apache-sling-scripting-thymeleaf.git
commit ab81f83756a973b6225bde066e42dca3a00ed639 Author: Oliver Lietz <[email protected]> AuthorDate: Thu Apr 21 16:36:24 2016 +0000 SLING-5075 Upgrade Thymeleaf to 3.0 update to Thymeleaf 3.0.0.BETA03 and unbescape 1.1.3.RELEASE git-svn-id: https://svn.apache.org/repos/asf/sling/trunk/contrib/scripting/org.apache.sling.scripting.thymeleaf@1740352 13f79535-47bb-0310-9956-ffa450edef68 --- pom.xml | 4 +- .../SlingIncludeAttributeTagProcessor.java | 29 ++-- .../java/org/thymeleaf/engine/TemplateManager.java | 191 +++++++++++++++++---- .../templateresolver/AbstractTemplateResolver.java | 2 +- .../templateresolver/ITemplateResolver.java | 2 +- 5 files changed, 175 insertions(+), 53 deletions(-) diff --git a/pom.xml b/pom.xml index 2824f7e..56f9aa1 100644 --- a/pom.xml +++ b/pom.xml @@ -39,9 +39,9 @@ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> <sling.java.version>7</sling.java.version> - <org.thymeleaf.version>3.0.0.BETA02</org.thymeleaf.version> + <org.thymeleaf.version>3.0.0.BETA03</org.thymeleaf.version> <org.attoparser.version>2.0.0.BETA05</org.attoparser.version> - <org.unbescape.version>1.1.2.RELEASE</org.unbescape.version> + <org.unbescape.version>1.1.3.RELEASE</org.unbescape.version> <ognl.version>3.1.2</ognl.version> <com.fasterxml.jackson.version>2.6.3</com.fasterxml.jackson.version> </properties> diff --git a/src/main/java/org/apache/sling/scripting/thymeleaf/internal/processor/SlingIncludeAttributeTagProcessor.java b/src/main/java/org/apache/sling/scripting/thymeleaf/internal/processor/SlingIncludeAttributeTagProcessor.java index 1676cf7..295d7c1 100644 --- a/src/main/java/org/apache/sling/scripting/thymeleaf/internal/processor/SlingIncludeAttributeTagProcessor.java +++ b/src/main/java/org/apache/sling/scripting/thymeleaf/internal/processor/SlingIncludeAttributeTagProcessor.java @@ -36,7 +36,6 @@ import org.slf4j.LoggerFactory; import org.thymeleaf.IEngineConfiguration; import org.thymeleaf.context.ITemplateContext; import org.thymeleaf.engine.AttributeName; -import org.thymeleaf.model.IElementAttributes; import org.thymeleaf.model.IProcessableElementTag; import org.thymeleaf.processor.element.AbstractAttributeTagProcessor; import org.thymeleaf.processor.element.IElementTagStructureHandler; @@ -90,11 +89,11 @@ public class SlingIncludeAttributeTagProcessor extends AbstractAttributeTagProce resource = (Resource) include; } // request dispatcher options - final RequestDispatcherOptions requestDispatcherOptions = prepareRequestDispatcherOptions(expressionParser, templateContext, processableElementTag); + final RequestDispatcherOptions requestDispatcherOptions = prepareRequestDispatcherOptions(expressionParser, templateContext, processableElementTag, elementTagStructureHandler); // dispatch final String content = dispatch(resource, path, slingHttpServletRequest, slingHttpServletResponse, requestDispatcherOptions); // add output - final Boolean unwrap = (Boolean) parseAttribute(expressionParser, templateContext, processableElementTag, UNWRAP_ATTRIBUTE_NAME); + final Boolean unwrap = (Boolean) parseAttribute(expressionParser, templateContext, processableElementTag, elementTagStructureHandler, UNWRAP_ATTRIBUTE_NAME); if (unwrap != null && unwrap) { elementTagStructureHandler.replaceWith(content, false); } else { @@ -105,30 +104,22 @@ public class SlingIncludeAttributeTagProcessor extends AbstractAttributeTagProce } } - protected Object parseAttribute(final IStandardExpressionParser expressionParser, final ITemplateContext templateContext, final IProcessableElementTag processableElementTag, final String name) { - final IElementAttributes attributes = processableElementTag.getAttributes(); - final String value = attributes.getValue(dialectPrefix, name); + protected Object parseAttribute(final IStandardExpressionParser expressionParser, final ITemplateContext templateContext, final IProcessableElementTag processableElementTag, final IElementTagStructureHandler elementTagStructureHandler, final String name) { + final String value = processableElementTag.getAttributeValue(dialectPrefix, name); Object result = null; if (value != null) { final IStandardExpression expression = expressionParser.parseExpression(templateContext, value); result = expression.execute(templateContext); } - attributes.removeAttribute(dialectPrefix, name); + elementTagStructureHandler.removeAttribute(dialectPrefix, name); return result; } - protected RequestDispatcherOptions prepareRequestDispatcherOptions(final IStandardExpressionParser expressionParser, final ITemplateContext templateContext, final IProcessableElementTag processableElementTag) { - final String resourceType = (String) parseAttribute(expressionParser, templateContext, processableElementTag, RESOURCE_TYPE_ATTRIBUTE_NAME); - processableElementTag.getAttributes().removeAttribute(dialectPrefix, RESOURCE_TYPE_ATTRIBUTE_NAME); - - final String replaceSelectors = (String) parseAttribute(expressionParser, templateContext, processableElementTag, REPLACE_SELECTORS_ATTRIBUTE_NAME); - processableElementTag.getAttributes().removeAttribute(dialectPrefix, REPLACE_SELECTORS_ATTRIBUTE_NAME); - - final String addSelectors = (String) parseAttribute(expressionParser, templateContext, processableElementTag, ADD_SELECTORS_ATTRIBUTE_NAME); - processableElementTag.getAttributes().removeAttribute(dialectPrefix, ADD_SELECTORS_ATTRIBUTE_NAME); - - final String replaceSuffix = (String) parseAttribute(expressionParser, templateContext, processableElementTag, REPLACE_SUFFIX_ATTRIBUTE_NAME); - processableElementTag.getAttributes().removeAttribute(dialectPrefix, REPLACE_SUFFIX_ATTRIBUTE_NAME); + protected RequestDispatcherOptions prepareRequestDispatcherOptions(final IStandardExpressionParser expressionParser, final ITemplateContext templateContext, final IProcessableElementTag processableElementTag, final IElementTagStructureHandler elementTagStructureHandler) { + final String resourceType = (String) parseAttribute(expressionParser, templateContext, processableElementTag, elementTagStructureHandler, RESOURCE_TYPE_ATTRIBUTE_NAME); + final String replaceSelectors = (String) parseAttribute(expressionParser, templateContext, processableElementTag, elementTagStructureHandler, REPLACE_SELECTORS_ATTRIBUTE_NAME); + final String addSelectors = (String) parseAttribute(expressionParser, templateContext, processableElementTag, elementTagStructureHandler, ADD_SELECTORS_ATTRIBUTE_NAME); + final String replaceSuffix = (String) parseAttribute(expressionParser, templateContext, processableElementTag, elementTagStructureHandler, REPLACE_SUFFIX_ATTRIBUTE_NAME); final RequestDispatcherOptions options = new RequestDispatcherOptions(); options.setForceResourceType(resourceType); diff --git a/src/main/java/org/thymeleaf/engine/TemplateManager.java b/src/main/java/org/thymeleaf/engine/TemplateManager.java index 469ae95..28b34d8 100644 --- a/src/main/java/org/thymeleaf/engine/TemplateManager.java +++ b/src/main/java/org/thymeleaf/engine/TemplateManager.java @@ -1,7 +1,7 @@ /* * ============================================================================= * - * Copyright (c) 2011-2014, The THYMELEAF team (http://www.thymeleaf.org) + * Copyright (c) 2011-2016, The THYMELEAF team (http://www.thymeleaf.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -291,15 +291,9 @@ public final class TemplateManager { /* - * Build the TemplateModel that we will end up returning - */ - final TemplateModel templateModel = new TemplateModel(this.configuration, templateData); - - - /* * Create the Template Handler that will be in charge of building the TemplateModel */ - final ModelBuilderTemplateHandler builderHandler = new ModelBuilderTemplateHandler(templateModel.getInternalModel()); + final ModelBuilderTemplateHandler builderHandler = new ModelBuilderTemplateHandler(this.configuration, templateData); /* @@ -311,6 +305,8 @@ public final class TemplateManager { ownerTemplate, template, cleanTemplateSelectors, templateData.getTemplateResource(), templateData.getTemplateMode(), templateResolution.getUseDecoupledLogic(), builderHandler); + final TemplateModel templateModel = builderHandler.getModel(); + /* * Cache the template if it is cacheable @@ -358,16 +354,15 @@ public final class TemplateManager { final IEngineContext engineContext = EngineContextManager.prepareEngineContext(this.configuration, templateData, context.getTemplateResolutionAttributes(), context); - final TemplateModel preProcessedTemplateModel = new TemplateModel(this.configuration, templateData); - final ModelBuilderTemplateHandler builderHandler = new ModelBuilderTemplateHandler(preProcessedTemplateModel.getInternalModel()); + final ModelBuilderTemplateHandler builderHandler = new ModelBuilderTemplateHandler(this.configuration, templateData); final ITemplateHandler processingHandlerChain = createTemplateProcessingHandlerChain(engineContext, true, false, builderHandler, null); - templateModel.getInternalModel().process(processingHandlerChain); + templateModel.process(processingHandlerChain); EngineContextManager.disposeEngineContext(engineContext); - return preProcessedTemplateModel; + return builderHandler.getModel(); } @@ -441,19 +436,13 @@ public final class TemplateManager { /* - * Build the TemplateModel + * 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 TemplateModel parsedTemplate = new TemplateModel(this.configuration, templateData); - - - /* - * Create the Template Handler that will be in charge of building the TemplateModel - */ - final ModelBuilderTemplateHandler builderHandler = new ModelBuilderTemplateHandler(parsedTemplate.getInternalModel()); + final ModelBuilderTemplateHandler builderHandler = new ModelBuilderTemplateHandler(this.configuration, templateData); /* @@ -463,6 +452,8 @@ public final class TemplateManager { // 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 @@ -526,7 +517,7 @@ public final class TemplateManager { /* * Process the template */ - template.getInternalModel().process(processingHandlerChain); + template.process(processingHandlerChain); /* @@ -599,7 +590,7 @@ public final class TemplateManager { final ITemplateHandler processingHandlerChain = createTemplateProcessingHandlerChain(engineContext, true, true, processorTemplateHandler, writer); - cached.getInternalModel().process(processingHandlerChain); + cached.process(processingHandlerChain); EngineContextManager.disposeEngineContext(engineContext); @@ -652,23 +643,23 @@ public final class TemplateManager { */ if (templateResolution.getValidity().isCacheable() && this.templateCache != null) { - // Build the TemplateModel - final TemplateModel templateModel = new TemplateModel(this.configuration, templateData); - // Create the handler chain to create the Template object - final ModelBuilderTemplateHandler builderHandler = new ModelBuilderTemplateHandler(templateModel.getInternalModel()); + final ModelBuilderTemplateHandler builderHandler = new ModelBuilderTemplateHandler(this.configuration, templateData); - // Process the cached template itself + // 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.getInternalModel().process(processingHandlerChain); + templateModel.process(processingHandlerChain); } else { @@ -690,6 +681,146 @@ public final class TemplateManager { } + public ThrottledTemplateProcessor parseAndProcessThrottled( + 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( + null, // ownerTemplate + template, templateSelectors, + 0, 0, // lineOffset, colOffset + templateMode, + templateResolutionAttributes); + + + /* + * Instantiate the throttling artifacts + */ + final TemplateFlowController flowController = new TemplateFlowController(); + final ThrottledTemplateWriter throttledTemplateWriter = new ThrottledTemplateWriter(template, flowController, writer); + + + /* + * 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); + + } + + @@ -802,7 +933,7 @@ public final class TemplateManager { */ if (setPreProcessors) { final Set<IPreProcessor> preProcessors = configuration.getPreProcessors(context.getTemplateMode()); - if (preProcessors != null) { + if (preProcessors != null && preProcessors.size() > 0) { for (final IPreProcessor preProcessor : preProcessors) { final Class<? extends ITemplateHandler> preProcessorClass = preProcessor.getHandlerClass(); final ITemplateHandler preProcessorHandler; @@ -845,7 +976,7 @@ public final class TemplateManager { */ if (setPostProcessors) { final Set<IPostProcessor> postProcessors = configuration.getPostProcessors(context.getTemplateMode()); - if (postProcessors != null) { + if (postProcessors != null && postProcessors.size() > 0) { for (final IPostProcessor postProcessor : postProcessors) { final Class<? extends ITemplateHandler> postProcessorClass = postProcessor.getHandlerClass(); final ITemplateHandler postProcessorHandler; diff --git a/src/main/java/org/thymeleaf/templateresolver/AbstractTemplateResolver.java b/src/main/java/org/thymeleaf/templateresolver/AbstractTemplateResolver.java index 8fc2092..e3eb4cf 100755 --- a/src/main/java/org/thymeleaf/templateresolver/AbstractTemplateResolver.java +++ b/src/main/java/org/thymeleaf/templateresolver/AbstractTemplateResolver.java @@ -1,7 +1,7 @@ /* * ============================================================================= * - * Copyright (c) 2011-2014, The THYMELEAF team (http://www.thymeleaf.org) + * Copyright (c) 2011-2016, The THYMELEAF team (http://www.thymeleaf.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/org/thymeleaf/templateresolver/ITemplateResolver.java b/src/main/java/org/thymeleaf/templateresolver/ITemplateResolver.java index 0bd62b9..eb4fc55 100755 --- a/src/main/java/org/thymeleaf/templateresolver/ITemplateResolver.java +++ b/src/main/java/org/thymeleaf/templateresolver/ITemplateResolver.java @@ -1,7 +1,7 @@ /* * ============================================================================= * - * Copyright (c) 2011-2014, The THYMELEAF team (http://www.thymeleaf.org) + * Copyright (c) 2011-2016, The THYMELEAF team (http://www.thymeleaf.org) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. -- To stop receiving notification emails like this one, please contact "[email protected]" <[email protected]>.
