use of org.thymeleaf.engine.TemplateModel in project thymeleaf by thymeleaf.
the class StandardUtextTagProcessor method doProcess.
@Override
protected void doProcess(final ITemplateContext context, final IProcessableElementTag tag, final AttributeName attributeName, final String attributeValue, final IElementTagStructureHandler structureHandler) {
final IEngineConfiguration configuration = context.getConfiguration();
final IStandardExpressionParser expressionParser = StandardExpressions.getExpressionParser(configuration);
final IStandardExpression expression = expressionParser.parseExpression(context, attributeValue);
final Object expressionResult;
if (expression != null && expression instanceof FragmentExpression) {
// This is merely a FragmentExpression (not complex, not combined with anything), so we can apply a shortcut
// so that we don't require a "null" result for this expression if the template does not exist. That will
// save a call to resource.exists() which might be costly.
final FragmentExpression.ExecutedFragmentExpression executedFragmentExpression = FragmentExpression.createExecutedFragmentExpression(context, (FragmentExpression) expression);
expressionResult = FragmentExpression.resolveExecutedFragmentExpression(context, executedFragmentExpression, true);
} else {
expressionResult = expression.execute(context, StandardExpressionExecutionContext.RESTRICTED);
}
// If result is no-op, there's nothing to execute
if (expressionResult == NoOpToken.VALUE) {
return;
}
/*
* First of all we should check whether the expression result is a Fragment so that, in such case, we can
* avoid creating a String in memory for it and just append its model.
*/
if (expressionResult != null && expressionResult instanceof Fragment) {
if (expressionResult == Fragment.EMPTY_FRAGMENT) {
structureHandler.removeBody();
return;
}
structureHandler.setBody(((Fragment) expressionResult).getTemplateModel(), false);
return;
}
final String unescapedTextStr = (expressionResult == null ? "" : expressionResult.toString());
/*
* We will check if there are configured post processors or not. The reason we do this is because output
* inserted as a result of a th:utext attribute, even if it might be markup, will never be considered as
* 'processable', i.e. no other processors/inliner will ever be able to act on it. The main reason for this
* is to protect against code injection.
*
* So the only other agents that would be able to modify these th:utext results are POST-PROCESSORS. And
* they will indeed need markup to have been parsed in order to separate text from structures, so that's why
* we check if there actually are any post-processors and, if not (most common case), simply output the
* expression result as if it were a mere (unescaped) text node.
*/
final Set<IPostProcessor> postProcessors = configuration.getPostProcessors(getTemplateMode());
if (postProcessors.isEmpty()) {
structureHandler.setBody(unescapedTextStr, false);
return;
}
/*
* We have post-processors, so from here one we will have to decide whether we need to parse the unescaped
* text or not...
*/
if (!mightContainStructures(unescapedTextStr)) {
// If this text contains no markup structures, there would be no need to parse it or treat it as markup!
structureHandler.setBody(unescapedTextStr, false);
return;
}
/*
* We have post-processors AND this text might contain structures, so there is no alternative but parsing
*/
final TemplateModel parsedFragment = configuration.getTemplateManager().parseString(context.getTemplateData(), unescapedTextStr, // we won't apply offset here because the inserted text does not really come from the template itself
0, // we won't apply offset here because the inserted text does not really come from the template itself
0, // No template mode forcing required
null, // useCache == false because we could potentially pollute the cache with too many entries (th:utext is too variable!)
false);
// Setting 'processable' to false avoiding text inliners processing already generated text,
// which in turn avoids code injection.
structureHandler.setBody(parsedFragment, false);
}
use of org.thymeleaf.engine.TemplateModel in project thymeleaf by thymeleaf.
the class StandardConditionalCommentProcessor method doProcess.
@Override
protected void doProcess(final ITemplateContext context, final IComment comment, final ICommentStructureHandler structureHandler) {
final StandardConditionalCommentUtils.ConditionalCommentParsingResult parsingResult = StandardConditionalCommentUtils.parseConditionalComment(comment);
if (parsingResult == null) {
// This is NOT a Conditional Comment. Just return
return;
}
final String commentStr = comment.getComment();
/*
* Next, we need to get the content of the Conditional Comment and process it as a piece of markup. In fact,
* we must process it as a template itself (a template fragment) so that all thymeleaf attributes and
* structures inside this content execute correctly, including references to context variables.
*/
final TemplateManager templateManager = context.getConfiguration().getTemplateManager();
final String parsableContent = commentStr.substring(parsingResult.getContentOffset(), parsingResult.getContentOffset() + parsingResult.getContentLen());
final TemplateModel templateModel = templateManager.parseString(context.getTemplateData(), parsableContent, comment.getLine(), comment.getCol(), // No need to force template mode
null, true);
final FastStringWriter writer = new FastStringWriter(200);
/*
* Rebuild the conditional comment start expression
*/
writer.write("[");
writer.write(commentStr, parsingResult.getStartExpressionOffset(), parsingResult.getStartExpressionLen());
writer.write("]>");
/*
* Process the parsable content
*/
templateManager.process(templateModel, context, writer);
/*
* Rebuild the conditional comment end expression
*/
writer.write("<![");
writer.write(commentStr, parsingResult.getEndExpressionOffset(), parsingResult.getEndExpressionLen());
writer.write("]");
/*
* Re-set the comment content, once processed
*/
structureHandler.setContent(writer.toString());
}
Aggregations