Index: src/main/java/com/xpn/xwiki/doc/XWikiDocument.java
===================================================================
--- src/main/java/com/xpn/xwiki/doc/XWikiDocument.java	(revision 28293)
+++ src/main/java/com/xpn/xwiki/doc/XWikiDocument.java	(working copy)
@@ -117,6 +117,7 @@
 import com.xpn.xwiki.content.parsers.ReplacementResultCollection;
 import com.xpn.xwiki.criteria.impl.RevisionCriteria;
 import com.xpn.xwiki.doc.rcs.XWikiRCSNodeInfo;
+import com.xpn.xwiki.internal.RenderingCache;
 import com.xpn.xwiki.internal.xml.DOMXMLWriter;
 import com.xpn.xwiki.internal.xml.XMLWriter;
 import com.xpn.xwiki.objects.BaseCollection;
@@ -421,6 +422,8 @@
 
     private Execution execution = Utils.getComponent(Execution.class);
 
+    private RenderingCache renderingCache = Utils.getComponent(RenderingCache.class);
+
     /**
      * @since 2.2M1
      */
@@ -779,30 +782,37 @@
         // document's context. For example this is true for the Admin page, see
         // http://jira.xwiki.org/jira/browse/XWIKI-4274 for more details.
 
-        String renderedContent;
-        Object isInRenderingEngine = context.get("isInRenderingEngine");
+        String source = getTranslatedContent(context);
 
-        try {
-            // This tells display() methods that we are inside the rendering engine and thus
-            // that they can return wiki syntax and not HTML syntax (which is needed when
-            // outside the rendering engine, i.e. when we're inside templates using only
-            // Velocity for example).
-            context.put("isInRenderingEngine", true);
+        String renderedContent = this.renderingCache.getRenderedContent(getDocumentReference(), source, context);
 
-            // If the Syntax id is "xwiki/1.0" then use the old rendering subsystem. Otherwise use the new one.
-            if (is10Syntax()) {
-                renderedContent = context.getWiki().getRenderingEngine().renderDocument(this, context);
-            } else {
-                renderedContent =
-                        performSyntaxConversion(getTranslatedContent(context), getSyntaxId(), targetSyntax, true);
-            }
-        } finally {
-            if (isInRenderingEngine != null) {
-                context.put("isInRenderingEngine", isInRenderingEngine);
-            } else {
-                context.remove("isInRenderingEngine");
+        if (renderedContent == null) {
+            Object isInRenderingEngine = context.get("isInRenderingEngine");
+
+            try {
+                // This tells display() methods that we are inside the rendering engine and thus
+                // that they can return wiki syntax and not HTML syntax (which is needed when
+                // outside the rendering engine, i.e. when we're inside templates using only
+                // Velocity for example).
+                context.put("isInRenderingEngine", true);
+
+                // If the Syntax id is "xwiki/1.0" then use the old rendering subsystem. Otherwise use the new one.
+                if (is10Syntax()) {
+                    renderedContent = context.getWiki().getRenderingEngine().renderDocument(this, context);
+                } else {
+                    renderedContent = performSyntaxConversion(source, getSyntaxId(), targetSyntax, true);
+                }
+
+                this.renderingCache.setRenderedContent(getDocumentReference(), source, renderedContent, context);
+            } finally {
+                if (isInRenderingEngine != null) {
+                    context.put("isInRenderingEngine", isInRenderingEngine);
+                } else {
+                    context.remove("isInRenderingEngine");
+                }
             }
         }
+
         return renderedContent;
     }
 
@@ -832,41 +842,47 @@
      */
     public String getRenderedContent(String text, String sourceSyntaxId, String targetSyntaxId, XWikiContext context)
     {
-        String result;
-        Map<String, Object> backup = new HashMap<String, Object>();
-        Object isInRenderingEngine = context.get("isInRenderingEngine");
-        try {
-            backupContext(backup, context);
-            setAsContextDoc(context);
+        String result = this.renderingCache.getRenderedContent(getDocumentReference(), text, context);
 
-            // This tells display() methods that we are inside the rendering engine and thus
-            // that they can return wiki syntax and not HTML syntax (which is needed when
-            // outside the rendering engine, i.e. when we're inside templates using only
-            // Velocity for example).
-            context.put("isInRenderingEngine", true);
+        if (result == null) {
+            Map<String, Object> backup = new HashMap<String, Object>();
+            Object isInRenderingEngine = context.get("isInRenderingEngine");
+            try {
+                backupContext(backup, context);
+                setAsContextDoc(context);
 
-            // If the Syntax id is "xwiki/1.0" then use the old rendering subsystem. Otherwise use the new one.
-            if (is10Syntax(sourceSyntaxId)) {
-                result = context.getWiki().getRenderingEngine().renderText(text, this, context);
-            } else {
-                SyntaxFactory syntaxFactory = Utils.getComponent(SyntaxFactory.class);
-                result =
-                        performSyntaxConversion(text, sourceSyntaxId,
-                            syntaxFactory.createSyntaxFromIdString(targetSyntaxId), true);
-            }
-        } catch (Exception e) {
-            // Failed to render for some reason. This method should normally throw an exception but this
-            // requires changing the signature of calling methods too.
-            LOG.warn(e);
-            result = "";
-        } finally {
-            restoreContext(backup, context);
-            if (isInRenderingEngine != null) {
-                context.put("isInRenderingEngine", isInRenderingEngine);
-            } else {
-                context.remove("isInRenderingEngine");
+                // This tells display() methods that we are inside the rendering engine and thus
+                // that they can return wiki syntax and not HTML syntax (which is needed when
+                // outside the rendering engine, i.e. when we're inside templates using only
+                // Velocity for example).
+                context.put("isInRenderingEngine", true);
+
+                // If the Syntax id is "xwiki/1.0" then use the old rendering subsystem. Otherwise use the new one.
+                if (is10Syntax(sourceSyntaxId)) {
+                    result = context.getWiki().getRenderingEngine().renderText(text, this, context);
+                } else {
+                    SyntaxFactory syntaxFactory = Utils.getComponent(SyntaxFactory.class);
+                    result =
+                        performSyntaxConversion(text, sourceSyntaxId, syntaxFactory
+                            .createSyntaxFromIdString(targetSyntaxId), true);
+                }
+
+                this.renderingCache.setRenderedContent(getDocumentReference(), text, result, context);
+            } catch (Exception e) {
+                // Failed to render for some reason. This method should normally throw an exception but this
+                // requires changing the signature of calling methods too.
+                LOG.warn(e);
+                result = "";
+            } finally {
+                restoreContext(backup, context);
+                if (isInRenderingEngine != null) {
+                    context.put("isInRenderingEngine", isInRenderingEngine);
+                } else {
+                    context.remove("isInRenderingEngine");
+                }
             }
         }
+
         return result;
     }
 
Index: src/main/java/com/xpn/xwiki/internal/RenderingCache.java
===================================================================
--- src/main/java/com/xpn/xwiki/internal/RenderingCache.java	(revision 0)
+++ src/main/java/com/xpn/xwiki/internal/RenderingCache.java	(revision 0)
@@ -0,0 +1,34 @@
+/*
+ * 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 com.xpn.xwiki.internal;
+
+import org.xwiki.component.annotation.ComponentRole;
+import org.xwiki.model.reference.DocumentReference;
+
+import com.xpn.xwiki.XWikiContext;
+
+@ComponentRole
+public interface RenderingCache
+{
+    public String getRenderedContent(DocumentReference documentReference, String source, XWikiContext context);
+
+    public void setRenderedContent(DocumentReference documentReference, String source, String renderedContent,
+        XWikiContext context);
+}
Index: src/main/java/com/xpn/xwiki/internal/DefaultRenderingCache.java
===================================================================
--- src/main/java/com/xpn/xwiki/internal/DefaultRenderingCache.java	(revision 0)
+++ src/main/java/com/xpn/xwiki/internal/DefaultRenderingCache.java	(revision 0)
@@ -0,0 +1,134 @@
+/*
+ * 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 com.xpn.xwiki.internal;
+
+import java.util.regex.Pattern;
+
+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.model.reference.DocumentReference;
+import org.xwiki.model.reference.EntityReferenceSerializer;
+
+import com.xpn.xwiki.XWikiContext;
+
+@Component
+public class DefaultRenderingCache implements RenderingCache, Initializable
+{
+    private static final String CACHEID = "core.renderingcache";
+
+    @Requirement
+    private RenderingCacheConfiguration configuration;
+
+    @Requirement
+    private CacheManager cacheManager;
+
+    @Requirement
+    private EntityReferenceSerializer<String> serializer;
+
+    private Cache<String> cache;
+
+    public void initialize() throws InitializationException
+    {
+        if (this.configuration.isEnabled()) {
+            try {
+                CacheConfiguration cacheConfiguration = new CacheConfiguration();
+                cacheConfiguration.setConfigurationId("CACHEID");
+                LRUEvictionConfiguration lru = new LRUEvictionConfiguration();
+                lru.setMaxEntries(this.configuration.getSize());
+                lru.setTimeToLive(this.configuration.getDuration());
+                cacheConfiguration.put(LRUEvictionConfiguration.CONFIGURATIONID, lru);
+
+                this.cache = this.cacheManager.createNewCache(cacheConfiguration);
+            } catch (CacheException e) {
+                throw new InitializationException("Failed to initialize core rendering cache", e);
+            }
+        }
+    }
+
+    public String getRenderedContent(DocumentReference documentReference, String source, XWikiContext context)
+    {
+        String renderedContent = null;
+
+        if (this.cache != null) {
+            String refresh = context.getRequest() != null ? context.getRequest().getParameter("refresh") : null;
+
+            if (!"1".equals(refresh)) {
+                String documentReferenceString = this.serializer.serialize(documentReference);
+
+                if (isCached(documentReferenceString)) {
+                    renderedContent = this.cache.get(getKey(documentReferenceString, source, context));
+                }
+            }
+        }
+
+        return renderedContent;
+    }
+
+    public void setRenderedContent(DocumentReference documentReference, String source, String renderedContent,
+        XWikiContext context)
+    {
+        if (this.configuration.isEnabled()) {
+            String documentReferenceString = this.serializer.serialize(documentReference);
+
+            if (isCached(documentReferenceString)) {
+                this.cache.set(getKey(documentReferenceString, source, context), renderedContent);
+            }
+        }
+    }
+
+    private String getKey(String documentReferenceString, String source, XWikiContext context)
+    {
+        StringBuffer buffer = new StringBuffer();
+
+        buffer.append(documentReferenceString);
+        buffer.append(':');
+        buffer.append(source);
+        buffer.append(':');
+        buffer.append(context.getAction() != null ? context.getAction() : "view");
+        buffer.append(':');
+        buffer.append(context.getLanguage() != null ? context.getLanguage() : "");
+        buffer.append(':');
+
+        String queryString =
+            context.getRequest() != null && context.getRequest().getQueryString() != null ? context.getRequest()
+                .getQueryString() : "";
+        buffer.append(queryString.replaceAll("\\&?refresh=1", ""));
+
+        return buffer.toString();
+    }
+
+    private boolean isCached(String documentReference)
+    {
+        for (Pattern pattern : this.configuration.getDocuments()) {
+            if (pattern.matcher(documentReference).matches()) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+}
Index: src/main/java/com/xpn/xwiki/internal/RenderingCacheConfiguration.java
===================================================================
--- src/main/java/com/xpn/xwiki/internal/RenderingCacheConfiguration.java	(revision 0)
+++ src/main/java/com/xpn/xwiki/internal/RenderingCacheConfiguration.java	(revision 0)
@@ -0,0 +1,37 @@
+/*
+ * 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 com.xpn.xwiki.internal;
+
+import java.util.List;
+import java.util.regex.Pattern;
+
+import org.xwiki.component.annotation.ComponentRole;
+
+@ComponentRole
+public interface RenderingCacheConfiguration
+{
+    boolean isEnabled();
+
+    List<Pattern> getDocuments();
+
+    int getDuration();
+
+    int getSize();
+}
Index: src/main/java/com/xpn/xwiki/internal/DefaultRenderingCacheConfiguration.java
===================================================================
--- src/main/java/com/xpn/xwiki/internal/DefaultRenderingCacheConfiguration.java	(revision 0)
+++ src/main/java/com/xpn/xwiki/internal/DefaultRenderingCacheConfiguration.java	(revision 0)
@@ -0,0 +1,86 @@
+/*
+ * 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 com.xpn.xwiki.internal;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import org.xwiki.component.annotation.Component;
+import org.xwiki.component.annotation.Requirement;
+import org.xwiki.configuration.ConfigurationSource;
+
+@Component
+public class DefaultRenderingCacheConfiguration implements RenderingCacheConfiguration
+{
+    private static final String PREFIX = "core.renderingcache.";
+
+    private static final String PROPNAME_ENABLED = PREFIX + "enabled";
+
+    private static final String PROPNAME_DOCUMENTS = PREFIX + "documents";
+
+    private static final String PROPNAME_DURATION = PREFIX + "duration";
+
+    private static final int PROPVALUE_DURATION = 300;
+
+    private static final String PROPNAME_SIZE = PREFIX + "size";
+
+    private static final int PROPVALUE_SIZE = 100;
+
+    /**
+     * Defines from where to read the rendering configuration data.
+     */
+    @Requirement("xwikiproperties")
+    private ConfigurationSource configuration;
+
+    private List<Pattern> patternList;
+
+    public boolean isEnabled()
+    {
+        return this.configuration.getProperty(PROPNAME_ENABLED, false);
+    }
+
+    public List<Pattern> getDocuments()
+    {
+        if (this.patternList == null) {
+            List<String> patternStringList = this.configuration.getProperty(PROPNAME_DOCUMENTS, List.class);
+
+            if (patternStringList != null) {
+                this.patternList = new ArrayList<Pattern>(patternStringList.size());
+
+                for (String patternString : patternStringList) {
+                    this.patternList.add(Pattern.compile(patternString));
+                }
+            }
+        }
+
+        return this.patternList;
+    }
+
+    public int getDuration()
+    {
+        return this.configuration.getProperty(PROPNAME_DURATION, PROPVALUE_DURATION);
+    }
+
+    public int getSize()
+    {
+        return this.configuration.getProperty(PROPNAME_SIZE, PROPVALUE_SIZE);
+    }
+}
Index: src/main/resources/ApplicationResources.properties
===================================================================
--- src/main/resources/ApplicationResources.properties	(revision 28293)
+++ src/main/resources/ApplicationResources.properties	(working copy)
@@ -1301,7 +1301,7 @@
 rendering.macro.error.content.description=
 rendering.macro.warning.name=Warning Message
 rendering.macro.warning.description=Displays a warning message note.
-rendering.macro.warning.content.description=
+rendering.macro.warning.content.description=Any wiki content.
 rendering.macro.box.name=Box
 rendering.macro.box.description=Draw a box around provided content.
 rendering.macro.box.content.description=the content to put in the box
Index: src/main/resources/META-INF/components.txt
===================================================================
--- src/main/resources/META-INF/components.txt	(revision 28293)
+++ src/main/resources/META-INF/components.txt	(working copy)
@@ -32,4 +32,6 @@
 com.xpn.xwiki.internal.XWikiStubContextInitializer
 com.xpn.xwiki.internal.DefaultXWikiStubContextProvider
 com.xpn.xwiki.internal.observation.remote.converter.DocumentEventConverter
-com.xpn.xwiki.internal.observation.remote.converter.ActionExecutionEventConverter
\ No newline at end of file
+com.xpn.xwiki.internal.observation.remote.converter.ActionExecutionEventConverter
+com.xpn.xwiki.internal.DefaultRenderingCache
+com.xpn.xwiki.internal.DefaultRenderingCacheConfiguration
\ No newline at end of file
