Rework how the action link on the ExceptionReport page are constructed

Previously, the approach was very susceptible to further exceptions while generating the page activation context for the failed page.
diff --git a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/ExceptionReport.java b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/ExceptionReport.java
index 248b347..06208e0 100644
--- a/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/ExceptionReport.java
+++ b/tapestry-core/src/main/java/org/apache/tapestry5/corelib/pages/ExceptionReport.java
@@ -12,7 +12,9 @@
 
 package org.apache.tapestry5.corelib.pages;
 
+import org.apache.tapestry5.ComponentResources;
 import org.apache.tapestry5.EventContext;
+import org.apache.tapestry5.Link;
 import org.apache.tapestry5.SymbolConstants;
 import org.apache.tapestry5.alerts.AlertManager;
 import org.apache.tapestry5.annotations.ContentType;
@@ -78,9 +80,6 @@
     @Property
     private String propertyName;
 
-    @Property
-    private String failurePage;
-
     @Inject
     private RequestGlobals requestGlobals;
 
@@ -108,6 +107,29 @@
     @Property
     private ThreadInfo thread;
 
+    @Inject
+    private ComponentResources resources;
+
+    private String failurePage;
+
+    /**
+     * A link the user may press to perform an action (e.g., "Reload page").
+     */
+    public static class ActionLink
+    {
+        public final String uri, label;
+
+
+        public ActionLink(String uri, String label)
+        {
+            this.uri = uri;
+            this.label = label;
+        }
+    }
+
+    @Property
+    private ActionLink actionLink;
+
     public class ThreadInfo implements Comparable<ThreadInfo>
     {
         public final String className, name, state, flags;
@@ -153,26 +175,73 @@
     {
         rootException = exception;
 
+        rootURL = baseURLSource.getBaseURL(request.isSecure());
+
+        // Capture this now ... before the gears are shifted around to make ExceptionReport the active page.
         failurePage = (request.getAttribute(InternalConstants.ACTIVE_PAGE_LOADED) == null)
                 ? null
                 : requestGlobals.getActivePageName();
-
-        rootURL = baseURLSource.getBaseURL(request.isSecure());
     }
 
-    public Object[] getReloadContext()
+    private static void add(List<ActionLink> links, Link link, String format, Object... arguments)
     {
-        return pageActivationContextCollector.collectPageActivationContext(failurePage);
+        String label = String.format(format, arguments);
+        links.add(new ActionLink(link.toURI(), label));
     }
 
-    Object onActionFromReloadFirst(EventContext reloadContext)
+    public List<ActionLink> getActionLinks()
+    {
+        List<ActionLink> links = CollectionFactory.newList();
+
+        if (failurePage != null)
+        {
+
+            try
+            {
+
+                Object[] pac = pageActivationContextCollector.collectPageActivationContext(failurePage);
+
+                add(links,
+                        linkSource.createPageRenderLinkWithContext(failurePage, pac),
+                        "Go to page <strong>%s</strong>", failurePage);
+
+                if (! productionMode)
+                {
+                    add(links,
+                            resources.createEventLink("reloadFirst", pac).addParameter("loadPage", failurePage),
+                            "Go to page <strong>%s</strong> (with reload)", failurePage);
+                }
+
+            } catch (Throwable t)
+            {
+                // Ignore.
+            }
+
+            links.add(new ActionLink(rootURL,
+                    String.format("Go to <strong>%s</strong>", rootURL)));
+
+
+            if (! productionMode) {
+                add(links,
+                        resources.createEventLink("reloadFirst"),
+                        "Go to <strong>%s</strong> (with reload)", rootURL);
+
+            }
+        }
+
+        return links;
+    }
+
+
+
+    Object onReloadFirst(EventContext reloadContext)
     {
         reloadHelper.forceReload();
 
         return linkSource.createPageRenderLinkWithContext(urlEncoder.decode(request.getParameter("loadPage")), reloadContext);
     }
 
-    Object onActionFromReloadRoot() throws MalformedURLException
+    Object onReloadRoot() throws MalformedURLException
     {
         reloadHelper.forceReload();
 
diff --git a/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/pages/ExceptionReport.tml b/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/pages/ExceptionReport.tml
index 74cdc1e..25a031c 100644
--- a/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/pages/ExceptionReport.tml
+++ b/tapestry-core/src/main/resources/org/apache/tapestry5/corelib/pages/ExceptionReport.tml
@@ -41,28 +41,12 @@
                     <div class="panel-footer">
 
                         <div class="btn-toolbar btn-group-xs">
-                            <t:if test="failurePage">
-                                <t:pagelink page="prop:failurePage" class="btn btn-default">Go to page
-                                    <strong>${failurePage}</strong>
-                                </t:pagelink>
-                                <t:if test="showReload">
-                                    <t:actionlink t:id="reloadFirst" parameters="{'loadPage': failurePage}"
-                                                  context="reloadContext" class="btn btn-default">Go to page
-                                        <strong>${failurePage}</strong>
-                                        (with reload)
-                                    </t:actionlink>
-                                </t:if>
-                            </t:if>
-                            <a href="/" class="btn btn-default">Go to
-                                <strong>${rootURL}</strong>
-                            </a>
-                            <t:if test="showReload">
-                                <t:actionLink t:id="reloadRoot" class="btn btn-default">
-                                    Go to
-                                    <strong>${rootURL}</strong>
-                                    (with reload)
-                                </t:actionLink>
-                            </t:if>
+                            <t:loop source="actionLinks" value="actionLink">
+                                <a href="${actionLink.uri}" class="btn btn-default">
+                                    <t:outputRaw value="actionLink.label"/>
+                                </a>
+                            </t:loop>
+
                         </div>
                     </div>
                     <t:if test="showReload">