Search in sources :

Example 16 with IEngineConfiguration

use of org.thymeleaf.IEngineConfiguration in project thymeleaf-tests by thymeleaf.

the class SpringResourceTemplateResolverSpring4Test method testResolveTemplate.

@Test
public void testResolveTemplate() throws Exception {
    final SpringTemplateEngine templateEngine = new SpringTemplateEngine();
    final IEngineConfiguration configuration = templateEngine.getConfiguration();
    final String templateLocation = "spring5/templateresolver/test.html";
    final ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:spring5/templateresolver/applicationContext.xml");
    final SpringResourceTemplateResolver resolver = (SpringResourceTemplateResolver) context.getBean("springResourceTemplateResolver");
    final TemplateMode templateMode = resolver.getTemplateMode();
    Assert.assertEquals(TemplateMode.HTML, templateMode);
    final TemplateResolution resolution = resolver.resolveTemplate(configuration, null, "classpath:" + templateLocation, null);
    final ITemplateResource templateResource = resolution.getTemplateResource();
    final String templateResourceStr = IOUtils.toString(templateResource.reader());
    final String testResource = templateResourceStr.replace("\r", "");
    final String expected = ResourceUtils.read(ClassLoaderUtils.getClassLoader(SpringResourceTemplateResolverSpring4Test.class).getResourceAsStream(templateLocation), "US-ASCII", true).replace("\r", "");
    Assert.assertEquals(expected, testResource);
}
Also used : SpringTemplateEngine(org.thymeleaf.spring5.SpringTemplateEngine) TemplateMode(org.thymeleaf.templatemode.TemplateMode) IEngineConfiguration(org.thymeleaf.IEngineConfiguration) ClassPathXmlApplicationContext(org.springframework.context.support.ClassPathXmlApplicationContext) TemplateResolution(org.thymeleaf.templateresolver.TemplateResolution) ITemplateResource(org.thymeleaf.templateresource.ITemplateResource) Test(org.junit.Test)

Example 17 with IEngineConfiguration

use of org.thymeleaf.IEngineConfiguration in project thymeleaf by thymeleaf.

the class TemplateManager method createTemplateProcessingHandlerChain.

private static ITemplateHandler createTemplateProcessingHandlerChain(final IEngineContext context, final boolean setPreProcessors, final boolean setPostProcessors, final ITemplateHandler handler, final Writer writer) {
    final IEngineConfiguration configuration = context.getConfiguration();
    /*
         * Declare the pair of pointers that will allow us to build the chain of template handlers
         */
    ITemplateHandler firstHandler = null;
    ITemplateHandler lastHandler = null;
    /*
         * First type of handlers to be added: pre-processors (if any)
         */
    if (setPreProcessors) {
        final Set<IPreProcessor> preProcessors = configuration.getPreProcessors(context.getTemplateMode());
        if (preProcessors != null && preProcessors.size() > 0) {
            for (final IPreProcessor preProcessor : preProcessors) {
                final Class<? extends ITemplateHandler> preProcessorClass = preProcessor.getHandlerClass();
                final ITemplateHandler preProcessorHandler;
                try {
                    preProcessorHandler = preProcessorClass.newInstance();
                } catch (final Exception e) {
                    // This should never happen - class was already checked during configuration to contain a zero-arg constructor
                    throw new TemplateProcessingException("An exception happened during the creation of a new instance of pre-processor " + preProcessorClass.getClass().getName(), e);
                }
                // Initialize the pre-processor
                preProcessorHandler.setContext(context);
                if (firstHandler == null) {
                    firstHandler = preProcessorHandler;
                    lastHandler = preProcessorHandler;
                } else {
                    lastHandler.setNext(preProcessorHandler);
                    lastHandler = preProcessorHandler;
                }
            }
        }
    }
    /*
         * Initialize and add to the chain te Processor Handler itself, the central piece of the chain
         */
    handler.setContext(context);
    if (firstHandler == null) {
        firstHandler = handler;
        lastHandler = handler;
    } else {
        lastHandler.setNext(handler);
        lastHandler = handler;
    }
    /*
         * After the Processor Handler, we now must add the post-processors (if any)
         */
    if (setPostProcessors) {
        final Set<IPostProcessor> postProcessors = configuration.getPostProcessors(context.getTemplateMode());
        if (postProcessors != null && postProcessors.size() > 0) {
            for (final IPostProcessor postProcessor : postProcessors) {
                final Class<? extends ITemplateHandler> postProcessorClass = postProcessor.getHandlerClass();
                final ITemplateHandler postProcessorHandler;
                try {
                    postProcessorHandler = postProcessorClass.newInstance();
                } catch (final Exception e) {
                    // This should never happen - class was already checked during configuration to contain a zero-arg constructor
                    throw new TemplateProcessingException("An exception happened during the creation of a new instance of post-processor " + postProcessorClass.getClass().getName(), e);
                }
                // Initialize the pre-processor
                postProcessorHandler.setContext(context);
                if (firstHandler == null) {
                    firstHandler = postProcessorHandler;
                    lastHandler = postProcessorHandler;
                } else {
                    lastHandler.setNext(postProcessorHandler);
                    lastHandler = postProcessorHandler;
                }
            }
        }
    }
    /*
         * Last step: the OUTPUT HANDLER
         */
    if (writer != null) {
        final OutputTemplateHandler outputHandler = new OutputTemplateHandler(writer);
        outputHandler.setContext(context);
        if (firstHandler == null) {
            firstHandler = outputHandler;
        } else {
            lastHandler.setNext(outputHandler);
        }
    }
    return firstHandler;
}
Also used : IEngineConfiguration(org.thymeleaf.IEngineConfiguration) IPostProcessor(org.thymeleaf.postprocessor.IPostProcessor) TemplateProcessingException(org.thymeleaf.exceptions.TemplateProcessingException) IPreProcessor(org.thymeleaf.preprocessor.IPreProcessor) TemplateProcessingException(org.thymeleaf.exceptions.TemplateProcessingException) TemplateInputException(org.thymeleaf.exceptions.TemplateInputException)

Example 18 with IEngineConfiguration

use of org.thymeleaf.IEngineConfiguration in project thymeleaf by thymeleaf.

the class AbstractMarkupTemplateParser method parse.

private void parse(final IEngineConfiguration configuration, final String ownerTemplate, final String template, final Set<String> templateSelectors, final ITemplateResource resource, final int lineOffset, final int colOffset, final TemplateMode templateMode, final boolean useDecoupledLogic, final ITemplateHandler templateHandler) {
    if (templateMode == TemplateMode.HTML) {
        Validate.isTrue(this.html, "Parser is configured as XML, but HTML-mode template parsing is being requested");
    } else if (templateMode == TemplateMode.XML) {
        Validate.isTrue(!this.html, "Parser is configured as HTML, but XML-mode template parsing is being requested");
    } else {
        throw new IllegalArgumentException("Parser is configured as " + (this.html ? "HTML" : "XML") + " but an unsupported template mode " + "has been specified: " + templateMode);
    }
    // For a String template, we will use the ownerTemplate as templateName for its parsed events
    final String templateName = (resource != null ? template : ownerTemplate);
    try {
        // We might need to first check for the existence of decoupled logic in a separate resource
        final DecoupledTemplateLogic decoupledTemplateLogic = (useDecoupledLogic && resource != null ? DecoupledTemplateLogicUtils.computeDecoupledTemplateLogic(configuration, ownerTemplate, template, templateSelectors, resource, templateMode, this.parser) : null);
        // The final step of the handler chain will be the adapter that will convert attoparser's handler chain to thymeleaf's.
        IMarkupHandler handler = new TemplateHandlerAdapterMarkupHandler(templateName, templateHandler, configuration.getElementDefinitions(), configuration.getAttributeDefinitions(), templateMode, lineOffset, colOffset);
        // (which might see text blocks coming as several blocks instead of just one).
        if (configuration instanceof EngineConfiguration && ((EngineConfiguration) configuration).isModelReshapeable(templateMode)) {
            handler = new InlinedOutputExpressionMarkupHandler(configuration, templateMode, configuration.getStandardDialectPrefix(), handler);
        }
        // Precompute flags
        final boolean injectAttributes = decoupledTemplateLogic != null && decoupledTemplateLogic.hasInjectedAttributes();
        final boolean selectBlock = templateSelectors != null && !templateSelectors.isEmpty();
        // Pre-create reference resolver if needed, so that it can be used in both block and node selection
        final TemplateFragmentMarkupReferenceResolver referenceResolver;
        if (injectAttributes || selectBlock) {
            final String standardDialectPrefix = configuration.getStandardDialectPrefix();
            referenceResolver = (standardDialectPrefix != null ? TemplateFragmentMarkupReferenceResolver.forPrefix(this.html, standardDialectPrefix) : null);
        } else {
            referenceResolver = null;
        }
        // will be able to include in selectors code inside prototype-only comments.
        if (selectBlock) {
            handler = new BlockSelectorMarkupHandler(handler, templateSelectors.toArray(new String[templateSelectors.size()]), referenceResolver);
        }
        // comment block readers, so that we will be able to include in selectors code inside prototype-only comments.
        if (injectAttributes) {
            // This handler will be in charge of really injecting the attributes, reacting to the node-selection
            // signals sent by the NodeSelectorMarkupHandler configured below
            handler = new DecoupledTemplateLogicMarkupHandler(decoupledTemplateLogic, handler);
            // NOTE it is important that THIS IS THE FIRST NODE- OR BLOCK-SELECTION HANDLER TO BE APPLIED because
            // structures in the DecoupledTemplateLogicMarkupHandler will consider 0 (zero) as their injection
            // level of interest
            final Set<String> nodeSelectors = decoupledTemplateLogic.getAllInjectedAttributeSelectors();
            handler = new NodeSelectorMarkupHandler(handler, handler, nodeSelectors.toArray(new String[nodeSelectors.size()]), referenceResolver);
        }
        // Obtain the resource reader
        Reader templateReader = (resource != null ? resource.reader() : new StringReader(template));
        // Add the required reader wrappers in order to process parser-level and prototype-only comment blocks
        templateReader = new ParserLevelCommentMarkupReader(new PrototypeOnlyCommentMarkupReader(templateReader));
        this.parser.parse(templateReader, handler);
    } catch (final IOException e) {
        final String message = "An error happened during template parsing";
        throw new TemplateInputException(message, (resource != null ? resource.getDescription() : template), e);
    } catch (final ParseException e) {
        final String message = "An error happened during template parsing";
        if (e.getLine() != null && e.getCol() != null) {
            throw new TemplateInputException(message, (resource != null ? resource.getDescription() : template), e.getLine().intValue(), e.getCol().intValue(), e);
        }
        throw new TemplateInputException(message, (resource != null ? resource.getDescription() : template), e);
    }
}
Also used : DecoupledTemplateLogic(org.thymeleaf.templateparser.markup.decoupled.DecoupledTemplateLogic) NodeSelectorMarkupHandler(org.attoparser.select.NodeSelectorMarkupHandler) PrototypeOnlyCommentMarkupReader(org.thymeleaf.templateparser.reader.PrototypeOnlyCommentMarkupReader) Reader(java.io.Reader) StringReader(java.io.StringReader) ParserLevelCommentMarkupReader(org.thymeleaf.templateparser.reader.ParserLevelCommentMarkupReader) IOException(java.io.IOException) TemplateInputException(org.thymeleaf.exceptions.TemplateInputException) IMarkupHandler(org.attoparser.IMarkupHandler) TemplateHandlerAdapterMarkupHandler(org.thymeleaf.engine.TemplateHandlerAdapterMarkupHandler) IEngineConfiguration(org.thymeleaf.IEngineConfiguration) EngineConfiguration(org.thymeleaf.EngineConfiguration) StringReader(java.io.StringReader) ParserLevelCommentMarkupReader(org.thymeleaf.templateparser.reader.ParserLevelCommentMarkupReader) PrototypeOnlyCommentMarkupReader(org.thymeleaf.templateparser.reader.PrototypeOnlyCommentMarkupReader) ParseException(org.attoparser.ParseException) DecoupledTemplateLogicMarkupHandler(org.thymeleaf.templateparser.markup.decoupled.DecoupledTemplateLogicMarkupHandler) BlockSelectorMarkupHandler(org.attoparser.select.BlockSelectorMarkupHandler)

Example 19 with IEngineConfiguration

use of org.thymeleaf.IEngineConfiguration in project thymeleaf by thymeleaf.

the class ExpressionSequenceUtils method parseExpressionSequence.

public static ExpressionSequence parseExpressionSequence(final IExpressionContext context, final String input) {
    Validate.notNull(context, "Context cannot be null");
    Validate.notNull(input, "Input cannot be null");
    final String preprocessedInput = StandardExpressionPreprocessor.preprocess(context, input);
    final IEngineConfiguration configuration = context.getConfiguration();
    if (configuration != null) {
        final ExpressionSequence cachedExpressionSequence = ExpressionCache.getExpressionSequenceFromCache(configuration, preprocessedInput);
        if (cachedExpressionSequence != null) {
            return cachedExpressionSequence;
        }
    }
    final ExpressionSequence expressionSequence = internalParseExpressionSequence(preprocessedInput.trim());
    if (expressionSequence == null) {
        throw new TemplateProcessingException("Could not parse as expression sequence: \"" + input + "\"");
    }
    if (configuration != null) {
        ExpressionCache.putExpressionSequenceIntoCache(configuration, preprocessedInput, expressionSequence);
    }
    return expressionSequence;
}
Also used : IEngineConfiguration(org.thymeleaf.IEngineConfiguration) TemplateProcessingException(org.thymeleaf.exceptions.TemplateProcessingException)

Example 20 with IEngineConfiguration

use of org.thymeleaf.IEngineConfiguration in project thymeleaf by thymeleaf.

the class FragmentExpression method resolveExecutedFragmentExpression.

public static Fragment resolveExecutedFragmentExpression(final ITemplateContext context, final ExecutedFragmentExpression executedFragmentExpression, final boolean failIfNotExists) {
    if (executedFragmentExpression == ExecutedFragmentExpression.EMPTY_EXECUTED_FRAGMENT_EXPRESSION) {
        return Fragment.EMPTY_FRAGMENT;
    }
    final IEngineConfiguration configuration = context.getConfiguration();
    /*
         * COMPUTE template name as String
         */
    String templateName = resolveTemplateName(executedFragmentExpression);
    /*
         * COMPUTE fragment selector as String
         */
    final Set<String> fragments = resolveFragments(executedFragmentExpression);
    /*
         * RESOLVE THE FRAGMENT MODEL by using the TemplateManager. This means the fragment will be parsed and maybe
         * cached, and we will be returned an immutable model object
         */
    List<String> templateNameStack = null;
    // scan the template stack if template name is 'this' or an empty name is being used
    if (StringUtils.isEmptyOrWhitespace(templateName)) {
        if (fragments == null || fragments.isEmpty()) {
            return null;
        }
        templateNameStack = new ArrayList<String>(3);
        for (int i = context.getTemplateStack().size() - 1; i >= 0; i--) {
            templateNameStack.add(context.getTemplateStack().get(i).getTemplate());
        }
        templateName = templateNameStack.get(0);
    }
    TemplateModel fragmentModel;
    int i = 0;
    do {
        fragmentModel = configuration.getTemplateManager().parseStandalone(context, templateName, fragments, // we will not force the template mode
        null, // use the cache if possible, fragments are from template files
        true, // depending on the scenario we will consider a non exiting template a fail or not
        failIfNotExists);
        i++;
    } while (// template not found (only if resolver configuration allows)
    fragmentModel != null && // template found, but selector not found
    fragmentModel.size() <= 2 && // we have more templates to look into
    templateNameStack != null && // we have more templates to look into
    i < templateNameStack.size() && // post test -- need to parse at least 1x
    (templateName = templateNameStack.get(i)) != null);
    if (fragmentModel == null) {
        // such as "~{template} ? ~{default}"
        return null;
    }
    /*
         * We should now check if the resolved fragment actually exists or not (we know the template exists but,
         * did the fragment actually return anything at all?
         */
    // only templatestart/end
    final boolean fragmentIsEmpty = (fragmentModel.size() == 2);
    if (fragmentIsEmpty) {
        // either fail or simply return null
        if (failIfNotExists) {
            throw new TemplateInputException("Error resolving fragment: \"" + executedFragmentExpression.fragmentExpression.getStringRepresentation() + "\": " + "template or fragment could not be resolved");
        }
        return null;
    }
    /*
         * RETURN the expected Fragment object
         */
    return new Fragment(fragmentModel, executedFragmentExpression.fragmentParameters, executedFragmentExpression.syntheticParameters);
}
Also used : IEngineConfiguration(org.thymeleaf.IEngineConfiguration) TemplateModel(org.thymeleaf.engine.TemplateModel) TemplateInputException(org.thymeleaf.exceptions.TemplateInputException)

Aggregations

IEngineConfiguration (org.thymeleaf.IEngineConfiguration)45 Test (org.junit.Test)26 LinkedHashMap (java.util.LinkedHashMap)15 ServletContext (javax.servlet.ServletContext)14 HttpServletRequest (javax.servlet.http.HttpServletRequest)14 HttpServletResponse (javax.servlet.http.HttpServletResponse)14 WebEngineContext (org.thymeleaf.context.WebEngineContext)14 EngineContext (org.thymeleaf.context.EngineContext)10 TemplateProcessingException (org.thymeleaf.exceptions.TemplateProcessingException)8 TemplateInputException (org.thymeleaf.exceptions.TemplateInputException)6 IOException (java.io.IOException)3 ArrayList (java.util.ArrayList)3 EngineConfiguration (org.thymeleaf.EngineConfiguration)3 TemplateModel (org.thymeleaf.engine.TemplateModel)3 IPostProcessor (org.thymeleaf.postprocessor.IPostProcessor)3 File (java.io.File)2 FileInputStream (java.io.FileInputStream)2 InputStreamReader (java.io.InputStreamReader)2 Reader (java.io.Reader)2 StringReader (java.io.StringReader)2