Index: xwiki-rendering/xwiki-rendering-macros/xwiki-rendering-macro-cache/pom.xml
===================================================================
--- xwiki-rendering/xwiki-rendering-macros/xwiki-rendering-macro-cache/pom.xml (revision )
+++ xwiki-rendering/xwiki-rendering-macros/xwiki-rendering-macro-cache/pom.xml (revision )
@@ -0,0 +1,84 @@
+
+
+
+
+
+ 4.0.0
+
+ org.xwiki.platform
+ xwiki-core-rendering-macros-parent
+ 2.7-SNAPSHOT
+
+ xwiki-core-rendering-macro-cache
+ XWiki Platform - Core - Rendering - Macro - Cache
+ XWiki Platform - Core - Rendering - Macro - Cache
+
+
+ org.xwiki.platform
+ xwiki-core-cache-api
+ ${project.version}
+
+
+ org.xwiki.platform
+ xwiki-core-cache-jbosscache
+ ${project.version}
+ test
+
+
+ org.xwiki.platform
+ xwiki-core-velocity
+ ${project.version}
+ test
+
+
+ org.xwiki.platform
+ xwiki-core-rendering-macro-velocity
+ ${project.version}
+ test
+
+
+ org.xwiki.platform
+ xwiki-core-rendering-macro-velocity
+ ${project.version}
+ test-jar
+ test
+
+
+ org.xwiki.platform
+ xwiki-core-rendering-macro-script
+ ${project.version}
+ test-jar
+ test
+
+
+ org.xwiki.platform
+ xwiki-core-observation-local
+ ${project.version}
+ test
+
+
+
+
+ true
+
+
Index: xwiki-rendering/xwiki-rendering-macros/xwiki-rendering-macro-box/src/main/java/org/xwiki/rendering/macro/box/AbstractBoxMacro.java
===================================================================
--- xwiki-rendering/xwiki-rendering-macros/xwiki-rendering-macro-box/src/main/java/org/xwiki/rendering/macro/box/AbstractBoxMacro.java (revision 32251)
+++ xwiki-rendering/xwiki-rendering-macros/xwiki-rendering-macro-box/src/main/java/org/xwiki/rendering/macro/box/AbstractBoxMacro.java (revision )
@@ -31,7 +31,7 @@
import org.xwiki.rendering.block.GroupBlock;
import org.xwiki.rendering.block.ImageBlock;
import org.xwiki.rendering.block.NewLineBlock;
-import org.xwiki.rendering.internal.macro.box.MacroContentParser;
+import org.xwiki.rendering.internal.macro.MacroContentParser;
import org.xwiki.rendering.listener.Format;
import org.xwiki.rendering.listener.reference.ResourceReference;
import org.xwiki.rendering.listener.reference.ResourceType;
Index: xwiki-rendering/xwiki-rendering-macros/xwiki-rendering-macro-box/src/main/java/org/xwiki/rendering/internal/macro/box/DefaultMacroContentParser.java
===================================================================
--- xwiki-rendering/xwiki-rendering-macros/xwiki-rendering-macro-box/src/main/java/org/xwiki/rendering/internal/macro/box/DefaultMacroContentParser.java (revision 32251)
+++ xwiki-rendering/xwiki-rendering-transformations/xwiki-rendering-transformation-macro/src/main/java/org/xwiki/rendering/internal/macro/DefaultMacroContentParser.java (revision )
@@ -17,7 +17,7 @@
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
-package org.xwiki.rendering.internal.macro.box;
+package org.xwiki.rendering.internal.macro;
import java.io.StringReader;
import java.util.List;
@@ -33,10 +33,10 @@
import org.xwiki.rendering.util.ParserUtils;
/**
- * Default implementation for {@link org.xwiki.rendering.internal.macro.box.MacroContentParser}.
+ * Default implementation for {@link org.xwiki.rendering.internal.macro.MacroContentParser}.
*
* @version $Id$
- * @since 2.6RC1
+ * @since 3.0M1
*/
@Component
public class DefaultMacroContentParser implements MacroContentParser
Index: xwiki-rendering/xwiki-rendering-macros/xwiki-rendering-macro-cache/src/test/java/org/xwiki/rendering/internal/macro/cache/CacheMacroTest.java
===================================================================
--- xwiki-rendering/xwiki-rendering-macros/xwiki-rendering-macro-cache/src/test/java/org/xwiki/rendering/internal/macro/cache/CacheMacroTest.java (revision )
+++ xwiki-rendering/xwiki-rendering-macros/xwiki-rendering-macro-cache/src/test/java/org/xwiki/rendering/internal/macro/cache/CacheMacroTest.java (revision )
@@ -0,0 +1,168 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.macro.cache;
+
+import java.io.StringWriter;
+import java.util.List;
+
+import org.junit.*;
+import org.xwiki.rendering.block.Block;
+import org.xwiki.rendering.internal.transformation.macro.MacroTransformation;
+import org.xwiki.rendering.macro.Macro;
+import org.xwiki.rendering.macro.cache.CacheMacroParameters;
+import org.xwiki.rendering.macro.script.ScriptMockSetup;
+import org.xwiki.rendering.renderer.PrintRendererFactory;
+import org.xwiki.rendering.syntax.Syntax;
+import org.xwiki.rendering.transformation.MacroTransformationContext;
+import org.xwiki.rendering.transformation.Transformation;
+import org.xwiki.test.AbstractComponentTestCase;
+import org.xwiki.velocity.VelocityManager;
+
+import static org.xwiki.rendering.scaffolding.BlockAssert.*;
+
+/**
+ * Unit tests for {@link CacheMacro}.
+ *
+ * @version $Id$
+ * @since 3.0M1
+ */
+public class CacheMacroTest extends AbstractComponentTestCase
+{
+ private ScriptMockSetup mockSetup;
+
+ private CacheMacro cacheMacro;
+
+ private PrintRendererFactory rendererFactory;
+
+ @Override
+ protected void registerComponents() throws Exception
+ {
+ super.registerComponents();
+
+ this.mockSetup = new ScriptMockSetup(getMockery(), getComponentManager());
+ this.cacheMacro = (CacheMacro) getComponentManager().lookup(Macro.class, "cache");
+ this.rendererFactory = getComponentManager().lookup(PrintRendererFactory.class, "event/1.0");
+ }
+
+ @Test
+ public void testExecuteWhenNoIdAndSameContent() throws Exception
+ {
+ String expected = "beginDocument\n"
+ + "beginMacroMarkerStandalone [velocity] [] [$var]\n"
+ + "beginParagraph\n"
+ + "onWord [content]\n"
+ + "endParagraph\n"
+ + "endMacroMarkerStandalone [velocity] [] [$var]\n"
+ + "endDocument";
+
+ CacheMacroParameters params = new CacheMacroParameters();
+ MacroTransformationContext context = createMacroTransformationContext();
+
+ VelocityManager velocityManager = getComponentManager().lookup(VelocityManager.class);
+ StringWriter writer = new StringWriter();
+ velocityManager.getVelocityEngine().evaluate(velocityManager.getVelocityContext(), writer, "template",
+ "#set ($var = 'content')");
+
+ List result = this.cacheMacro.execute(params, "{{velocity}}$var{{/velocity}}", context);
+ assertBlocks(expected, result, this.rendererFactory);
+
+ // Execute a second time with a different value for the velocity $var variable to ensure the returned result
+ // is the cached one.
+ velocityManager.getVelocityEngine().evaluate(velocityManager.getVelocityContext(), writer, "template",
+ "#set ($var = 'newcontent')");
+ result = this.cacheMacro.execute(params, "{{velocity}}$var{{/velocity}}", context);
+ assertBlocks(expected, result, this.rendererFactory);
+ }
+
+ @Test
+ public void testExecuteWhenNoIdAndDifferentContent() throws Exception
+ {
+ String expected1 = "beginDocument\n"
+ + "beginMacroMarkerStandalone [velocity] [] [$var]\n"
+ + "beginParagraph\n"
+ + "onWord [content]\n"
+ + "endParagraph\n"
+ + "endMacroMarkerStandalone [velocity] [] [$var]\n"
+ + "endDocument";
+
+ String expected2 = "beginDocument\n"
+ + "beginMacroMarkerStandalone [velocity] [] [$var##]\n"
+ + "beginParagraph\n"
+ + "onWord [newcontent]\n"
+ + "endParagraph\n"
+ + "endMacroMarkerStandalone [velocity] [] [$var##]\n"
+ + "endDocument";
+
+ CacheMacroParameters params = new CacheMacroParameters();
+ MacroTransformationContext context = createMacroTransformationContext();
+
+ VelocityManager velocityManager = getComponentManager().lookup(VelocityManager.class);
+ StringWriter writer = new StringWriter();
+ velocityManager.getVelocityEngine().evaluate(velocityManager.getVelocityContext(), writer, "template",
+ "#set ($var = 'content')");
+
+ List result = this.cacheMacro.execute(params, "{{velocity}}$var{{/velocity}}", context);
+ assertBlocks(expected1, result, this.rendererFactory);
+
+ // Execute a second time with a different cache macro content to ensure it's not cached
+ velocityManager.getVelocityEngine().evaluate(velocityManager.getVelocityContext(), writer, "template",
+ "#set ($var = 'newcontent')");
+ result = this.cacheMacro.execute(params, "{{velocity}}$var##{{/velocity}}", context);
+ assertBlocks(expected2, result, this.rendererFactory);
+ }
+
+ @Test
+ public void testExecuteWhenSameIdAndDifferentContent() throws Exception
+ {
+ String expected = "beginDocument\n"
+ + "beginMacroMarkerStandalone [velocity] [] [$var]\n"
+ + "beginParagraph\n"
+ + "onWord [content]\n"
+ + "endParagraph\n"
+ + "endMacroMarkerStandalone [velocity] [] [$var]\n"
+ + "endDocument";
+
+ CacheMacroParameters params = new CacheMacroParameters();
+ params.setId("uniqueid");
+ MacroTransformationContext context = createMacroTransformationContext();
+
+ VelocityManager velocityManager = getComponentManager().lookup(VelocityManager.class);
+ StringWriter writer = new StringWriter();
+ velocityManager.getVelocityEngine().evaluate(velocityManager.getVelocityContext(), writer, "template",
+ "#set ($var = 'content')");
+
+ List result = this.cacheMacro.execute(params, "{{velocity}}$var{{/velocity}}", context);
+ assertBlocks(expected, result, this.rendererFactory);
+
+ // Execute a second time with a different content but with the same id, to ensure the returned result
+ // is the cached one.
+ result = this.cacheMacro.execute(params, "whatever here...", context);
+ assertBlocks(expected, result, this.rendererFactory);
+ }
+ private MacroTransformationContext createMacroTransformationContext() throws Exception
+ {
+ MacroTransformation macroTransformation =
+ (MacroTransformation) getComponentManager().lookup(Transformation.class, "macro");
+ MacroTransformationContext context = new MacroTransformationContext();
+ context.setTransformation(macroTransformation);
+ context.setSyntax(Syntax.XWIKI_2_0);
+ return context;
+ }
+}
Index: xwiki-rendering/xwiki-rendering-macros/pom.xml
===================================================================
--- xwiki-rendering/xwiki-rendering-macros/pom.xml (revision 32361)
+++ xwiki-rendering/xwiki-rendering-macros/pom.xml (revision )
@@ -123,5 +123,6 @@
xwiki-rendering-macro-php
xwiki-rendering-macro-container
xwiki-rendering-macro-dashboard
+ xwiki-rendering-macro-cache
Index: xwiki-rendering/xwiki-rendering-macros/xwiki-rendering-macro-box/src/main/resources/META-INF/components.txt
===================================================================
--- xwiki-rendering/xwiki-rendering-macros/xwiki-rendering-macro-box/src/main/resources/META-INF/components.txt (revision 32251)
+++ xwiki-rendering/xwiki-rendering-macros/xwiki-rendering-macro-box/src/main/resources/META-INF/components.txt (revision )
@@ -1,2 +1,1 @@
-org.xwiki.rendering.internal.macro.box.DefaultBoxMacro
+org.xwiki.rendering.internal.macro.box.DefaultBoxMacro
\ No newline at end of file
-org.xwiki.rendering.internal.macro.box.DefaultMacroContentParser
\ No newline at end of file
Index: xwiki-rendering/xwiki-rendering-transformations/xwiki-rendering-transformation-macro/src/main/resources/META-INF/components.txt
===================================================================
--- xwiki-rendering/xwiki-rendering-transformations/xwiki-rendering-transformation-macro/src/main/resources/META-INF/components.txt (revision 32245)
+++ xwiki-rendering/xwiki-rendering-transformations/xwiki-rendering-transformation-macro/src/main/resources/META-INF/components.txt (revision )
@@ -2,5 +2,6 @@
org.xwiki.rendering.internal.macro.DefaultMacroCategoryManager
org.xwiki.rendering.internal.macro.DefaultMacroIdFactory
org.xwiki.rendering.internal.macro.ResourceReferenceConverter
+org.xwiki.rendering.internal.macro.DefaultMacroContentParser
org.xwiki.rendering.internal.transformation.macro.MacroTransformation
org.xwiki.rendering.internal.transformation.macro.DefaultMacroTransformationConfiguration
Index: xwiki-rendering/xwiki-rendering-macros/xwiki-rendering-macro-cache/src/main/resources/META-INF/components.txt
===================================================================
--- xwiki-rendering/xwiki-rendering-macros/xwiki-rendering-macro-cache/src/main/resources/META-INF/components.txt (revision )
+++ xwiki-rendering/xwiki-rendering-macros/xwiki-rendering-macro-cache/src/main/resources/META-INF/components.txt (revision )
@@ -0,0 +1,1 @@
+org.xwiki.rendering.internal.macro.cache.CacheMacro
\ No newline at end of file
Index: xwiki-rendering/xwiki-rendering-macros/xwiki-rendering-macro-box/src/main/java/org/xwiki/rendering/internal/macro/box/MacroContentParser.java
===================================================================
--- xwiki-rendering/xwiki-rendering-macros/xwiki-rendering-macro-box/src/main/java/org/xwiki/rendering/internal/macro/box/MacroContentParser.java (revision 32251)
+++ xwiki-rendering/xwiki-rendering-transformations/xwiki-rendering-transformation-macro/src/main/java/org/xwiki/rendering/internal/macro/MacroContentParser.java (revision )
@@ -17,7 +17,7 @@
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
-package org.xwiki.rendering.internal.macro.box;
+package org.xwiki.rendering.internal.macro;
import java.util.List;
@@ -30,7 +30,7 @@
* Parses content of a macro field (parameter, macro content) in a given syntax.
*
* @version $Id$
- * @since 2.6RC1
+ * @since 3.0M1
*/
@ComponentRole
public interface MacroContentParser
Index: pom.xml
===================================================================
--- pom.xml (revision 33089)
+++ pom.xml (revision )
@@ -196,6 +196,7 @@
org/xwiki/officeimporter/openoffice/OpenOfficeManager$ManagerState
org/xwiki/url/standard/StandardURLConfiguration
+ org/xwiki/rendering/macro/box/AbstractBoxMacro
Index: xwiki-rendering/xwiki-rendering-macros/xwiki-rendering-macro-cache/src/main/java/org/xwiki/rendering/internal/macro/cache/CacheMacro.java
===================================================================
--- xwiki-rendering/xwiki-rendering-macros/xwiki-rendering-macro-cache/src/main/java/org/xwiki/rendering/internal/macro/cache/CacheMacro.java (revision )
+++ xwiki-rendering/xwiki-rendering-macros/xwiki-rendering-macro-cache/src/main/java/org/xwiki/rendering/internal/macro/cache/CacheMacro.java (revision )
@@ -0,0 +1,162 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.internal.macro.cache;
+
+import java.util.List;
+
+import org.xwiki.cache.Cache;
+import org.xwiki.cache.CacheException;
+import org.xwiki.cache.CacheManager;
+import org.xwiki.cache.config.CacheConfiguration;
+import org.xwiki.cache.eviction.LRUEvictionConfiguration;
+import org.xwiki.component.annotation.Component;
+import org.xwiki.component.annotation.Requirement;
+import org.xwiki.component.phase.Initializable;
+import org.xwiki.component.phase.InitializationException;
+import org.xwiki.rendering.block.Block;
+import org.xwiki.rendering.block.XDOM;
+import org.xwiki.rendering.internal.macro.MacroContentParser;
+import org.xwiki.rendering.macro.AbstractMacro;
+import org.xwiki.rendering.macro.MacroExecutionException;
+import org.xwiki.rendering.macro.cache.CacheMacroParameters;
+import org.xwiki.rendering.macro.descriptor.DefaultContentDescriptor;
+import org.xwiki.rendering.transformation.MacroTransformationContext;
+import org.xwiki.rendering.transformation.TransformationContext;
+
+/**
+ * Provides Caching for the content of the macro.
+ *
+ * @version $Id$
+ * @since 3.0M1
+ */
+@Component("cache")
+public class CacheMacro extends AbstractMacro implements Initializable
+{
+ /**
+ * The description of the macro.
+ */
+ private static final String DESCRIPTION = "Caches content.";
+
+ /**
+ * The description of the macro content.
+ */
+ private static final String CONTENT_DESCRIPTION = "the content to cache.";
+
+ /**
+ * Used to create the macro content cache.
+ */
+ @Requirement
+ private CacheManager cacheManager;
+
+ /**
+ * The parser used to parse the content (when not cached).
+ */
+ @Requirement
+ private MacroContentParser contentParser;
+
+ /**
+ * The cache containing all cache macro contents.
+ */
+ private Cache contentCache;
+
+ /**
+ * Create and initialize the descriptor of the macro.
+ */
+ public CacheMacro()
+ {
+ super("Cache", DESCRIPTION, new DefaultContentDescriptor(CONTENT_DESCRIPTION), CacheMacroParameters.class);
+ setDefaultCategory(DEFAULT_CATEGORY_DEVELOPMENT);
+ }
+
+ /**
+ * {@inheritDoc}
+ * @see org.xwiki.component.phase.Initializable#initialize()
+ */
+ @Override
+ public void initialize() throws InitializationException
+ {
+ super.initialize();
+
+ // Create Cache
+ CacheConfiguration configuration = new CacheConfiguration();
+ //configuration.setConfigurationId("rendering.macro.cache");
+
+ LRUEvictionConfiguration lru = new LRUEvictionConfiguration();
+ lru.setMaxEntries(1000);
+ lru.setTimeToLive(300);
+ configuration.put(LRUEvictionConfiguration.CONFIGURATIONID, lru);
+
+ try {
+ this.contentCache = this.cacheManager.createNewLocalCache(configuration);
+ } catch (CacheException e) {
+ throw new InitializationException("Failed to create content cache", e);
+ }
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.macro.Macro#supportsInlineMode()
+ */
+ public boolean supportsInlineMode()
+ {
+ return true;
+ }
+
+ /**
+ * {@inheritDoc}
+ *
+ * @see org.xwiki.rendering.macro.Macro#execute(Object, String, MacroTransformationContext)
+ */
+ public List execute(CacheMacroParameters parameters, String content, MacroTransformationContext context)
+ throws MacroExecutionException
+ {
+ // Idea for improvement: use context.getId() (which contains the document name) as part of the cache key to
+ // make it even more unique (when the cache macro parameter id is not specified).
+ String cacheKey;
+ if (parameters.getId() != null) {
+ cacheKey = parameters.getId();
+ } else {
+ cacheKey = content;
+ }
+
+ List result = (List) this.contentCache.get(cacheKey);
+ if (result == null) {
+ // Run the parser for the syntax on the content
+ result = this.contentParser.parse(content, context.getSyntax(), context.isInline());
+ // Run the current transformation on the cache macro content. We need to do this since we want to cache
+ // the XDOM resulting from the execution of Macros because that's where lenghty processing happens.
+ if (context.getTransformation() != null) {
+ XDOM xdom = new XDOM(result);
+ TransformationContext txContext = new TransformationContext(xdom, context.getSyntax());
+ txContext.setId(context.getId());
+ try {
+ context.getTransformation().transform(xdom, txContext);
+ } catch (Exception e) {
+ throw new MacroExecutionException("Failed to perform transformation", e);
+ }
+ result = xdom.getChildren();
+ }
+ this.contentCache.set(cacheKey, result);
+ }
+
+ return result;
+ }
+}
Index: xwiki-rendering/xwiki-rendering-macros/xwiki-rendering-macro-cache/src/main/java/org/xwiki/rendering/macro/cache/CacheMacroParameters.java
===================================================================
--- xwiki-rendering/xwiki-rendering-macros/xwiki-rendering-macro-cache/src/main/java/org/xwiki/rendering/macro/cache/CacheMacroParameters.java (revision )
+++ xwiki-rendering/xwiki-rendering-macros/xwiki-rendering-macro-cache/src/main/java/org/xwiki/rendering/macro/cache/CacheMacroParameters.java (revision )
@@ -0,0 +1,56 @@
+/*
+ * See the NOTICE file distributed with this work for additional
+ * information regarding copyright ownership.
+ *
+ * This is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU Lesser General Public License as
+ * published by the Free Software Foundation; either version 2.1 of
+ * the License, or (at your option) any later version.
+ *
+ * This software is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this software; if not, write to the Free
+ * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
+ * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
+ */
+package org.xwiki.rendering.macro.cache;
+
+import org.xwiki.properties.annotation.PropertyDescription;
+
+/**
+ * Parameters for the Cache macro.
+ *
+ * @version $Id$
+ * @since 3.0M1
+ */
+public class CacheMacroParameters
+{
+ /**
+ * @see #getId()
+ */
+ private String id;
+
+ /**
+ * @return the optional unique id to use to cache the content. If not defined then use the content itself as the id
+ * but this doesn't guarantee unicity since the same content could be located on several pages with
+ * different results.
+ */
+ public String getId()
+ {
+ return this.id;
+ }
+
+ /**
+ * @param id refer to {@link #getId()}
+ */
+ @PropertyDescription("a unique id under which the content is cached")
+ public void setId(String id)
+ {
+ this.id = id;
+ }
+
+}