You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@roller.apache.org by gh...@apache.org on 2014/06/19 12:52:58 UTC

svn commit: r1603823 - in /roller/trunk/app/src/main: java/org/apache/roller/weblogger/ui/rendering/servlets/ java/org/apache/roller/weblogger/ui/rendering/util/ java/org/apache/roller/weblogger/ui/struts2/editor/ webapp/WEB-INF/jsps/editor/

Author: ghuber
Date: Thu Jun 19 10:52:58 2014
New Revision: 1603823

URL: http://svn.apache.org/r1603823
Log:
Make sure page hit counts are accurate ie we do not count page resources e.g. *.css files as page hits.

Modified:
    roller/trunk/app/src/main/java/org/apache/roller/weblogger/ui/rendering/servlets/PageServlet.java
    roller/trunk/app/src/main/java/org/apache/roller/weblogger/ui/rendering/util/WeblogPageRequest.java
    roller/trunk/app/src/main/java/org/apache/roller/weblogger/ui/struts2/editor/Maintenance.java
    roller/trunk/app/src/main/webapp/WEB-INF/jsps/editor/Maintenance.jsp

Modified: roller/trunk/app/src/main/java/org/apache/roller/weblogger/ui/rendering/servlets/PageServlet.java
URL: http://svn.apache.org/viewvc/roller/trunk/app/src/main/java/org/apache/roller/weblogger/ui/rendering/servlets/PageServlet.java?rev=1603823&r1=1603822&r2=1603823&view=diff
==============================================================================
--- roller/trunk/app/src/main/java/org/apache/roller/weblogger/ui/rendering/servlets/PageServlet.java (original)
+++ roller/trunk/app/src/main/java/org/apache/roller/weblogger/ui/rendering/servlets/PageServlet.java Thu Jun 19 10:52:58 2014
@@ -228,7 +228,8 @@ public class PageServlet extends HttpSer
 
         // cached content checking
         if ((!this.excludeOwnerPages || !pageRequest.isLoggedIn())
-                && request.getAttribute("skipCache") == null) {
+                && request.getAttribute("skipCache") == null
+                && request.getParameter("skipCache") == null) {
 
             CachedContent cachedContent;
             if (isSiteWide) {
@@ -242,7 +243,9 @@ public class PageServlet extends HttpSer
                 log.debug("HIT " + cacheKey);
 
                 // allow for hit counting
-                if (!isSiteWide) {
+                if (!isSiteWide
+                        && (pageRequest.isWebsitePageHit() || pageRequest
+                                .isOtherPageHit())) {
                     this.processHit(weblog);
                 }
 
@@ -349,7 +352,8 @@ public class PageServlet extends HttpSer
             invalid = true;
         }
         // locale view allowed only if weblog has enabled it
-        if (pageRequest.getLocale() != null && !pageRequest.getWeblog().isEnableMultiLang()) {
+        if (pageRequest.getLocale() != null
+                && !pageRequest.getWeblog().isEnableMultiLang()) {
             invalid = true;
         }
         if (pageRequest.getWeblogAnchor() != null) {
@@ -403,7 +407,9 @@ public class PageServlet extends HttpSer
         }
 
         // allow for hit counting
-        if (!isSiteWide) {
+        if (!isSiteWide
+                && (pageRequest.isWebsitePageHit() || pageRequest
+                        .isOtherPageHit())) {
             this.processHit(weblog);
         }
 
@@ -426,8 +432,8 @@ public class PageServlet extends HttpSer
         HashMap<String, Object> model = new HashMap<String, Object>();
         try {
             PageContext pageContext = JspFactory.getDefaultFactory()
-                    .getPageContext(this, request, response, "", false, RollerConstants.EIGHT_KB_IN_BYTES,
-                            true);
+                    .getPageContext(this, request, response, "", false,
+                            RollerConstants.EIGHT_KB_IN_BYTES, true);
 
             // special hack for menu tag
             request.setAttribute("pageRequest", pageRequest);
@@ -491,7 +497,8 @@ public class PageServlet extends HttpSer
         }
 
         // render content
-        CachedContent rendererOutput = new CachedContent(RollerConstants.TWENTYFOUR_KB_IN_BYTES, contentType);
+        CachedContent rendererOutput = new CachedContent(
+                RollerConstants.TWENTYFOUR_KB_IN_BYTES, contentType);
         try {
             log.debug("Doing rendering");
             renderer.render(model, rendererOutput.getCachedWriter());

Modified: roller/trunk/app/src/main/java/org/apache/roller/weblogger/ui/rendering/util/WeblogPageRequest.java
URL: http://svn.apache.org/viewvc/roller/trunk/app/src/main/java/org/apache/roller/weblogger/ui/rendering/util/WeblogPageRequest.java?rev=1603823&r1=1603822&r2=1603823&view=diff
==============================================================================
--- roller/trunk/app/src/main/java/org/apache/roller/weblogger/ui/rendering/util/WeblogPageRequest.java (original)
+++ roller/trunk/app/src/main/java/org/apache/roller/weblogger/ui/rendering/util/WeblogPageRequest.java Thu Jun 19 10:52:58 2014
@@ -37,21 +37,20 @@ import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
-
 /**
  * Represents a request for a Roller weblog page.
- *
+ * 
  * any url from ... /roller-ui/rendering/page/*
- *
+ * 
  * We use this class as a helper to parse an incoming url and sort out the
  * information embedded in the url for later use.
  */
 public class WeblogPageRequest extends WeblogRequest {
-    
+
     private static Log log = LogFactory.getLog(WeblogPageRequest.class);
-    
+
     private static final String PAGE_SERVLET = "/roller-ui/rendering/page";
-    
+
     // lightweight attributes
     private String context = null;
     private String weblogAnchor = null;
@@ -61,160 +60,191 @@ public class WeblogPageRequest extends W
     private List tags = null;
     private int pageNum = 0;
     private Map customParams = new HashMap();
-    
+
     // heavyweight attributes
     private WeblogEntry weblogEntry = null;
     private ThemeTemplate weblogPage = null;
     private WeblogCategory weblogCategory = null;
 
-    public WeblogPageRequest() {}
+    // Page hits
+    private boolean websitePageHit = false;
+    private boolean otherPageHit = false;
+
+    public WeblogPageRequest() {
+    }
 
     /**
      * Construct the WeblogPageRequest by parsing the incoming url
      */
-    public WeblogPageRequest(HttpServletRequest request) 
+    public WeblogPageRequest(HttpServletRequest request)
             throws InvalidRequestException {
-        
+
         // let our parent take care of their business first
         // parent determines weblog handle and locale if specified
         super(request);
-        
+
         String servlet = request.getServletPath();
-        
+
         // we only want the path info left over from after our parents parsing
         String pathInfo = this.getPathInfo();
-        
+
         // parse the request object and figure out what we've got
         log.debug("parsing path " + pathInfo);
-        
+
         // was this request bound for the right servlet?
-        if(!isValidDestination(servlet)) {
-            throw new InvalidRequestException("invalid destination for request, " +
-                    request.getRequestURL());
+        if (!isValidDestination(servlet)) {
+            throw new InvalidRequestException(
+                    "invalid destination for request, "
+                            + request.getRequestURL());
         }
-        
+
         /*
          * parse path info
-         *
+         * 
          * we expect one of the following forms of url ...
-         *
-         * /entry/<anchor> - permalink
-         * /date/<YYYYMMDD> - date collection view
-         * /category/<category> - category collection view
-         * /tags/<tag>+<tag> - tags
-         * /page/<pagelink> - custom page
-         *
+         * 
+         * /entry/<anchor> - permalink /date/<YYYYMMDD> - date collection view
+         * /category/<category> - category collection view /tags/<tag>+<tag> -
+         * tags /page/<pagelink> - custom page
+         * 
          * path info may be null, which indicates the weblog homepage
          */
-        if(pathInfo != null && pathInfo.trim().length() > 0) {
-            
+        if (pathInfo != null && pathInfo.trim().length() > 0) {
+
             // all views use 2 path elements
             String[] pathElements = pathInfo.split("/", 2);
-            
+
             // the first part of the path always represents the context
             this.context = pathElements[0];
-            
+
             // now check the rest of the path and extract other details
-            if(pathElements.length == 2) {
-                
-                if("entry".equals(this.context)) {
+            if (pathElements.length == 2) {
+
+                if ("entry".equals(this.context)) {
                     this.weblogAnchor = URLUtilities.decode(pathElements[1]);
-                    
-                } else if("date".equals(this.context)) {
-                    if(this.isValidDateString(pathElements[1])) {
+
+                    // Other page
+                    otherPageHit = true;
+
+                } else if ("date".equals(this.context)) {
+                    if (this.isValidDateString(pathElements[1])) {
                         this.weblogDate = pathElements[1];
                     } else {
-                        throw new InvalidRequestException("invalid date, "+
-                            request.getRequestURL());
+                        throw new InvalidRequestException("invalid date, "
+                                + request.getRequestURL());
                     }
-                    
-                } else if("category".equals(this.context)) {
-                    this.weblogCategoryName = URLUtilities.decode(pathElements[1]);
-                } else if("page".equals(this.context)) {
+
+                    // Other page
+                    otherPageHit = true;
+
+                } else if ("category".equals(this.context)) {
+                    this.weblogCategoryName = URLUtilities
+                            .decode(pathElements[1]);
+
+                    // Other page
+                    otherPageHit = true;
+
+                } else if ("page".equals(this.context)) {
                     this.weblogPageName = pathElements[1];
                     String tagsString = request.getParameter("tags");
                     if (tagsString != null) {
-                        this.tags = Utilities.splitStringAsTags(URLUtilities.decode(tagsString));
+                        this.tags = Utilities.splitStringAsTags(URLUtilities
+                                .decode(tagsString));
                     }
 
-                } else if("tags".equals(this.context)) {
+                    // Other page, we do not want css etc stuff so filter out
+                    if (!pathElements[1].contains(".")) {
+                        otherPageHit = true;
+                    }
+
+                } else if ("tags".equals(this.context)) {
                     String tagsString = pathElements[1].replace('+', ' ');
-                    this.tags = Utilities.splitStringAsTags(URLUtilities.decode(tagsString));                  
-                    int maxSize = WebloggerConfig.getIntProperty("tags.queries.maxIntersectionSize", 3);                  
-                    if(this.tags.size() > maxSize) {
-                        throw new InvalidRequestException("max number of tags allowed is " + maxSize + ", " + request.getRequestURL());
+                    this.tags = Utilities.splitStringAsTags(URLUtilities
+                            .decode(tagsString));
+                    int maxSize = WebloggerConfig.getIntProperty(
+                            "tags.queries.maxIntersectionSize", 3);
+                    if (this.tags.size() > maxSize) {
+                        throw new InvalidRequestException(
+                                "max number of tags allowed is " + maxSize
+                                        + ", " + request.getRequestURL());
                     }
+
+                    // Other page
+                    otherPageHit = true;
+
                 } else {
-                    throw new InvalidRequestException("context "+this.context+
-                            "not supported, "+request.getRequestURL());
+                    throw new InvalidRequestException("context " + this.context
+                            + "not supported, " + request.getRequestURL());
                 }
-                
+
             } else {
                 // empty data is only allowed for the tags section
-                if(!"tags".equals(this.context)) {
-                    throw new InvalidRequestException("invalid index page, "+
-                            request.getRequestURL());
+                if (!"tags".equals(this.context)) {
+                    throw new InvalidRequestException("invalid index page, "
+                            + request.getRequestURL());
                 }
             }
+        } else {
+            // default page
+            websitePageHit = true;
         }
-        
+
         /*
          * parse request parameters
-         *
-         * the only params we currently allow are:
-         *   date - specifies a weblog date string
-         *   cat - specifies a weblog category
-         *   anchor - specifies a weblog entry (old way)
-         *   entry - specifies a weblog entry
-         *
+         * 
+         * the only params we currently allow are: date - specifies a weblog
+         * date string cat - specifies a weblog category anchor - specifies a
+         * weblog entry (old way) entry - specifies a weblog entry
+         * 
          * we only allow request params if the path info is null or on user
-         * defined pages (for backwards compatability).  this way
-         * we prevent mixing of path based and query param style urls.
+         * defined pages (for backwards compatability). this way we prevent
+         * mixing of path based and query param style urls.
          */
-        if(pathInfo == null || this.weblogPageName != null) {
-            
+        if (pathInfo == null || this.weblogPageName != null) {
+
             // check for entry/anchor params which indicate permalink
-            if(request.getParameter("entry") != null) {
+            if (request.getParameter("entry") != null) {
                 String anchor = request.getParameter("entry");
-                if(StringUtils.isNotEmpty(anchor)) {
+                if (StringUtils.isNotEmpty(anchor)) {
                     this.weblogAnchor = anchor;
                 }
-            } else if(request.getParameter("anchor") != null) {
+            } else if (request.getParameter("anchor") != null) {
                 String anchor = request.getParameter("anchor");
-                if(StringUtils.isNotEmpty(anchor)) {
+                if (StringUtils.isNotEmpty(anchor)) {
                     this.weblogAnchor = anchor;
                 }
             }
-            
-            // only check for other params if we didn't find an anchor above or tags
-            if(this.weblogAnchor == null && this.tags == null) {
-                if(request.getParameter("date") != null) {
+
+            // only check for other params if we didn't find an anchor above or
+            // tags
+            if (this.weblogAnchor == null && this.tags == null) {
+                if (request.getParameter("date") != null) {
                     String date = request.getParameter("date");
-                    if(this.isValidDateString(date)) {
+                    if (this.isValidDateString(date)) {
                         this.weblogDate = date;
                     } else {
-                        throw new InvalidRequestException("invalid date, "+
-                                request.getRequestURL());
+                        throw new InvalidRequestException("invalid date, "
+                                + request.getRequestURL());
                     }
                 }
-                
-                if(request.getParameter("cat") != null) {
-                    this.weblogCategoryName =
-                            URLUtilities.decode(request.getParameter("cat"));
+
+                if (request.getParameter("cat") != null) {
+                    this.weblogCategoryName = URLUtilities.decode(request
+                            .getParameter("cat"));
                 }
             }
         }
-        
+
         // page request param is supported in all views
-        if(request.getParameter("page") != null) {
+        if (request.getParameter("page") != null) {
             String pageInt = request.getParameter("page");
             try {
                 this.pageNum = Integer.parseInt(pageInt);
-            } catch(NumberFormatException e) {
+            } catch (NumberFormatException e) {
                 // ignored, bad input
             }
         }
-        
+
         // build customParams Map, we remove built-in params because we only
         // want this map to represent params defined by the template author
         customParams = new HashMap(request.getParameterMap());
@@ -224,29 +254,26 @@ public class WeblogPageRequest extends W
         customParams.remove("cat");
         customParams.remove("page");
         customParams.remove("tags");
-            
-            
-        if(log.isDebugEnabled()) {
-            log.debug("context = "+this.context);
-            log.debug("weblogAnchor = "+this.weblogAnchor);
-            log.debug("weblogDate = "+this.weblogDate);
-            log.debug("weblogCategory = "+this.weblogCategoryName);
-            log.debug("tags = "+this.tags);
-            log.debug("weblogPage = "+this.weblogPageName);
-            log.debug("pageNum = "+this.pageNum);
+
+        if (log.isDebugEnabled()) {
+            log.debug("context = " + this.context);
+            log.debug("weblogAnchor = " + this.weblogAnchor);
+            log.debug("weblogDate = " + this.weblogDate);
+            log.debug("weblogCategory = " + this.weblogCategoryName);
+            log.debug("tags = " + this.tags);
+            log.debug("weblogPage = " + this.weblogPageName);
+            log.debug("pageNum = " + this.pageNum);
         }
     }
-    
-    
+
     boolean isValidDestination(String servlet) {
         return (servlet != null && PAGE_SERVLET.equals(servlet));
     }
-    
-    
+
     private boolean isValidDateString(String dateString) {
         // string must be all numeric and 6 or 8 characters
-        return (dateString != null && StringUtils.isNumeric(dateString) &&
-                (dateString.length() == 6 || dateString.length() == 8));
+        return (dateString != null && StringUtils.isNumeric(dateString) && (dateString
+                .length() == 6 || dateString.length() == 8));
     }
 
     public String getContext() {
@@ -304,26 +331,28 @@ public class WeblogPageRequest extends W
     public void setCustomParams(Map customParams) {
         this.customParams = customParams;
     }
-    
+
     public List getTags() {
-      return tags;
+        return tags;
     }
-    
+
     public void setTags(List tags) {
-      this.tags = tags;
+        this.tags = tags;
     }
-    
+
     public WeblogEntry getWeblogEntry() {
-        
-        if(weblogEntry == null && weblogAnchor != null) {
+
+        if (weblogEntry == null && weblogAnchor != null) {
             try {
-                WeblogEntryManager wmgr = WebloggerFactory.getWeblogger().getWeblogEntryManager();
-                weblogEntry = wmgr.getWeblogEntryByAnchor(getWeblog(), weblogAnchor);
+                WeblogEntryManager wmgr = WebloggerFactory.getWeblogger()
+                        .getWeblogEntryManager();
+                weblogEntry = wmgr.getWeblogEntryByAnchor(getWeblog(),
+                        weblogAnchor);
             } catch (WebloggerException ex) {
-                log.error("Error getting weblog entry "+weblogAnchor, ex);
+                log.error("Error getting weblog entry " + weblogAnchor, ex);
             }
         }
-        
+
         return weblogEntry;
     }
 
@@ -332,16 +361,16 @@ public class WeblogPageRequest extends W
     }
 
     public ThemeTemplate getWeblogPage() {
-        
 
-        if(weblogPage == null && weblogPageName != null) {
+        if (weblogPage == null && weblogPageName != null) {
             try {
-                weblogPage = getWeblog().getTheme().getTemplateByLink(weblogPageName);
+                weblogPage = getWeblog().getTheme().getTemplateByLink(
+                        weblogPageName);
             } catch (WebloggerException ex) {
-                log.error("Error getting weblog page "+weblogPageName, ex);
+                log.error("Error getting weblog page " + weblogPageName, ex);
             }
         }
-        
+
         return weblogPage;
     }
 
@@ -350,21 +379,63 @@ public class WeblogPageRequest extends W
     }
 
     public WeblogCategory getWeblogCategory() {
-        
-        if(weblogCategory == null && weblogCategoryName != null) {
+
+        if (weblogCategory == null && weblogCategoryName != null) {
             try {
-                WeblogEntryManager wmgr = WebloggerFactory.getWeblogger().getWeblogEntryManager();
-                weblogCategory = wmgr.getWeblogCategoryByName(getWeblog(), weblogCategoryName);
+                WeblogEntryManager wmgr = WebloggerFactory.getWeblogger()
+                        .getWeblogEntryManager();
+                weblogCategory = wmgr.getWeblogCategoryByName(getWeblog(),
+                        weblogCategoryName);
             } catch (WebloggerException ex) {
-                log.error("Error getting weblog category "+weblogCategoryName, ex);
+                log.error(
+                        "Error getting weblog category " + weblogCategoryName,
+                        ex);
             }
         }
-        
+
         return weblogCategory;
     }
 
     public void setWeblogCategory(WeblogCategory weblogCategory) {
         this.weblogCategory = weblogCategory;
     }
-    
+
+    /**
+     * Checks if is website page hit.
+     * 
+     * @return true, if is website page hit
+     */
+    public boolean isWebsitePageHit() {
+        return websitePageHit;
+    }
+
+    /**
+     * Sets the website page hit.
+     * 
+     * @param websitePageHit
+     *            the new website page hit
+     */
+    public void setWebsitePageHit(boolean websitePageHit) {
+        this.websitePageHit = websitePageHit;
+    }
+
+    /**
+     * Checks if is other page hit.
+     * 
+     * @return true, if is other page hit
+     */
+    public boolean isOtherPageHit() {
+        return otherPageHit;
+    }
+
+    /**
+     * Sets the other page hit.
+     * 
+     * @param otherPageHit
+     *            the new other page hit
+     */
+    public void setOtherPageHit(boolean otherPageHit) {
+        this.otherPageHit = otherPageHit;
+    }
+
 }

Modified: roller/trunk/app/src/main/java/org/apache/roller/weblogger/ui/struts2/editor/Maintenance.java
URL: http://svn.apache.org/viewvc/roller/trunk/app/src/main/java/org/apache/roller/weblogger/ui/struts2/editor/Maintenance.java?rev=1603823&r1=1603822&r2=1603823&view=diff
==============================================================================
--- roller/trunk/app/src/main/java/org/apache/roller/weblogger/ui/struts2/editor/Maintenance.java (original)
+++ roller/trunk/app/src/main/java/org/apache/roller/weblogger/ui/struts2/editor/Maintenance.java Thu Jun 19 10:52:58 2014
@@ -21,22 +21,23 @@ package org.apache.roller.weblogger.ui.s
 import java.util.Collections;
 import java.util.Date;
 import java.util.List;
+
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 import org.apache.roller.weblogger.business.search.IndexManager;
+import org.apache.roller.weblogger.business.WeblogEntryManager;
 import org.apache.roller.weblogger.business.WebloggerFactory;
 import org.apache.roller.weblogger.pojos.Weblog;
 import org.apache.roller.weblogger.pojos.WeblogPermission;
 import org.apache.roller.weblogger.ui.struts2.util.UIAction;
 import org.apache.roller.weblogger.util.cache.CacheManager;
 
-
 /**
- * Allows user to perform maintenance operations such as flushing
- * the page cache or re-indexing the search index.
+ * Allows user to perform maintenance operations such as flushing the page cache
+ * or re-indexing the search index.
  */
 public class Maintenance extends UIAction {
-    
+
     private static Log log = LogFactory.getLog(Maintenance.class);
 
     public Maintenance() {
@@ -44,59 +45,91 @@ public class Maintenance extends UIActio
         this.desiredMenu = "editor";
         this.pageTitle = "maintenance.title";
     }
-    
-    
+
     // admin perms required
     public List<String> requiredWeblogPermissionActions() {
         return Collections.singletonList(WeblogPermission.ADMIN);
     }
-    
-    
+
     public String execute() {
         return SUCCESS;
     }
-    
-    
+
     /**
      * Rebuild search index for weblog.
      */
     public String index() {
-        
+
         try {
-            IndexManager manager = WebloggerFactory.getWeblogger().getIndexManager();
+            IndexManager manager = WebloggerFactory.getWeblogger()
+                    .getIndexManager();
             manager.rebuildWebsiteIndex(getActionWeblog());
-            
+
             addMessage("maintenance.message.indexed");
         } catch (Exception ex) {
             log.error("Error doing index rebuild", ex);
             addError("maintenance.message.indexed.failure");
         }
-        
+
         return SUCCESS;
     }
 
-    
     /**
      * Flush page cache for weblog.
      */
     public String flushCache() {
-        
+
         try {
             Weblog weblog = getActionWeblog();
-            
+
             // some caches are based on weblog last-modified, so update it
             weblog.setLastModified(new Date());
-            
-            WebloggerFactory.getWeblogger().getWeblogManager().saveWeblog(weblog);
+
+            WebloggerFactory.getWeblogger().getWeblogManager()
+                    .saveWeblog(weblog);
             WebloggerFactory.getWeblogger().flush();
-            
+
             // also notify cache manager
             CacheManager.invalidate(weblog);
 
             addMessage("maintenance.message.flushed");
-            
+
+        } catch (Exception ex) {
+            log.error("Error saving weblog - " + getActionWeblog().getHandle(),
+                    ex);
+            addError("Error flushing page cache");
+        }
+
+        return SUCCESS;
+    }
+
+    /**
+     * Reset hit count for weblog.
+     */
+    public String reset() {
+
+        try {
+            Weblog weblog = getActionWeblog();
+
+            WeblogEntryManager mgr = WebloggerFactory.getWeblogger()
+                    .getWeblogEntryManager();
+            mgr.resetHitCount(weblog);
+
+            // some caches are based on weblog last-modified, so update it
+            weblog.setLastModified(new Date());
+
+            WebloggerFactory.getWeblogger().getWeblogManager()
+                    .saveWeblog(weblog);
+            WebloggerFactory.getWeblogger().flush();
+
+            // also notify cache manager
+            CacheManager.invalidate(weblog);
+
+            addMessage("maintenance.message.reset");
+
         } catch (Exception ex) {
-            log.error("Error saving weblog - "+getActionWeblog().getHandle(), ex);
+            log.error("Error saving weblog - " + getActionWeblog().getHandle(),
+                    ex);
             addError("Error flushing page cache");
         }
 

Modified: roller/trunk/app/src/main/webapp/WEB-INF/jsps/editor/Maintenance.jsp
URL: http://svn.apache.org/viewvc/roller/trunk/app/src/main/webapp/WEB-INF/jsps/editor/Maintenance.jsp?rev=1603823&r1=1603822&r2=1603823&view=diff
==============================================================================
--- roller/trunk/app/src/main/webapp/WEB-INF/jsps/editor/Maintenance.jsp (original)
+++ roller/trunk/app/src/main/webapp/WEB-INF/jsps/editor/Maintenance.jsp Thu Jun 19 10:52:58 2014
@@ -32,4 +32,8 @@
         <s:submit value="%{getText('maintenance.button.index')}" action="maintenance!index" />	
     </s:if>
 
+    <br /><br />
+    <s:text name="maintenance.prompt.reset" /><br /><br />
+    <s:submit value="%{getText('maintenance.button.reset')}" action="maintenance!reset" />
+
 </s:form>