diff --git a/dotCMS/src/main/java/com/dotcms/rendering/velocity/directive/DotDirective.java b/dotCMS/src/main/java/com/dotcms/rendering/velocity/directive/DotDirective.java index 006bbddc391d..30a9c231ea63 100644 --- a/dotCMS/src/main/java/com/dotcms/rendering/velocity/directive/DotDirective.java +++ b/dotCMS/src/main/java/com/dotcms/rendering/velocity/directive/DotDirective.java @@ -1,10 +1,14 @@ package com.dotcms.rendering.velocity.directive; import java.io.IOException; +import java.io.StringWriter; import java.io.Writer; +import java.util.Map; +import java.util.Optional; import javax.servlet.http.HttpServletRequest; +import com.dotmarketing.business.CacheLocator; import org.apache.velocity.Template; import org.apache.velocity.context.Context; import org.apache.velocity.context.InternalContextAdapter; @@ -18,7 +22,6 @@ import org.apache.velocity.runtime.parser.node.Node; import org.apache.velocity.runtime.parser.node.SimpleNode; -import com.dotcms.rendering.velocity.directive.RenderParams; import com.dotcms.rendering.velocity.services.VelocityType; import com.dotcms.rendering.velocity.util.VelocityUtil; @@ -70,8 +73,17 @@ final Template loadTemplate(InternalContextAdapter context, String templatePath } } - - + + /** + * Return the value from Cache if the Directive is using some kind of Cache level + * the default implementation return a Empty Optional. + * + * @return Value from cache + */ + public Optional getFromCache(final String[] arguments) { + return Optional.empty(); + } + final public boolean render(InternalContextAdapter context, Writer writer, Node node) throws IOException, ResourceNotFoundException, ParseErrorException, MethodInvocationException { @@ -84,11 +96,12 @@ final public boolean render(InternalContextAdapter context, Writer writer, Node arguments[i]= (value == null) ? null : value.toString(); } - - - - + final Optional fromCache = getFromCache(arguments); + if (fromCache.isPresent()) { + writer.write(fromCache.get()); + return true; + } RenderParams params = new RenderParams(request); @@ -98,7 +111,13 @@ final public boolean render(InternalContextAdapter context, Writer writer, Node throw new ResourceNotFoundException("null template"); } Template t = loadTemplate(context, templatePath); - return this.renderTemplate(context, writer, t, templatePath); + + final Writer innerWriter = new StringWriter(); + final boolean result = this.renderTemplate(context, innerWriter, t, templatePath); + this.afterRender(innerWriter.toString(), arguments); + writer.write(innerWriter.toString()); + + return result; } catch(ParseErrorException|ResourceNotFoundException rnfe){ context.remove("ContentIdentifier"); postRender(context); @@ -107,6 +126,16 @@ final public boolean render(InternalContextAdapter context, Writer writer, Node } + /** + * Call after render the Template, it allow you to do something before the return of + * the {@link DotDirective#render(InternalContextAdapter, Writer, Node)} + * + * @param render Template content after render + * @param arguments + */ + void afterRender(final String render, String[] arguments) { + + } final boolean renderTemplate(InternalContextAdapter context, final Writer writer, final Template t, final String templatePath) diff --git a/dotCMS/src/main/java/com/dotcms/rendering/velocity/directive/DotParse.java b/dotCMS/src/main/java/com/dotcms/rendering/velocity/directive/DotParse.java index b1aa06272785..fce3fff0cfe4 100644 --- a/dotCMS/src/main/java/com/dotcms/rendering/velocity/directive/DotParse.java +++ b/dotCMS/src/main/java/com/dotcms/rendering/velocity/directive/DotParse.java @@ -1,13 +1,16 @@ package com.dotcms.rendering.velocity.directive; -import com.dotcms.variant.business.web.VariantWebAPI.RenderContext; +import com.dotmarketing.business.CacheLocator; import com.dotmarketing.business.web.WebAPILocator; import java.io.File; +import java.io.Serializable; import java.io.Writer; +import java.util.Map; import java.util.Optional; import java.util.StringTokenizer; import javax.servlet.http.HttpServletRequest; import org.apache.velocity.context.Context; +import org.apache.velocity.context.InternalContextAdapter; import org.apache.velocity.exception.ResourceNotFoundException; import com.dotcms.contenttype.model.type.DotAssetContentType; import com.dotcms.util.ConversionUtils; @@ -31,10 +34,12 @@ import com.liferay.util.StringPool; import io.vavr.Tuple; import io.vavr.Tuple2; +import org.apache.velocity.runtime.parser.node.Node; public class DotParse extends DotDirective { + private final static String RENDER = "render"; private static final long serialVersionUID = 1L; private final String hostIndicator = "//"; @@ -190,7 +195,29 @@ private void throwNotResourceNotFoundException(final RenderParams params, final throw new ResourceNotFoundException(errorMessage); } + /** + * Call after render the Template, it allow you to do something before the return of + * the {@link DotDirective#render(InternalContextAdapter, Writer, Node)} + * + * @param render Template content after render + * @param arguments + */ + void afterRender(final String render, String[] arguments) { + if (arguments.length > 1) { + CacheLocator.getBlockDirectiveCache().add(getTTLCacheKey(arguments), Map.of(RENDER, render), Integer.parseInt(arguments[1])); + } + } + public Optional getFromCache(final String[] arguments) { + final Map valueFromCache = + CacheLocator.getBlockDirectiveCache().get(getTTLCacheKey(arguments)); + return UtilMethods.isSet(valueFromCache.get(RENDER)) ? Optional.of(valueFromCache.get(RENDER).toString()) : + Optional.empty(); + } + + private String getTTLCacheKey(String[] arguments) { + return getName() + "_" + arguments[0]; + } private Optional> resolveDotAsset(final RenderParams params, final String templatePath) throws DotDataException, DotSecurityException { @@ -229,8 +256,6 @@ private Optional> resolveDotAsset(final RenderParams final Identifier identifier = APILocator.getIdentifierAPI().find(conOpt.get().getIdentifier()); return Optional.of(Tuple.of(identifier, fieldVar)); - - } private Optional> resolveFileAsset(final RenderParams params,