FELIX-1988 Apply 6.vmstat.patch by Valentin Valchev (thanks) with the following change: The WebConsoleUtil.getVariableResolver now presets the default resolver created with the appRoot and pluginRoot properties from the respective request attributes

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@910873 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/WebConsoleUtil.java b/webconsole/src/main/java/org/apache/felix/webconsole/WebConsoleUtil.java
index fafd9d2..3e3e70a 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/WebConsoleUtil.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/WebConsoleUtil.java
@@ -54,10 +54,13 @@
     /**
      * Returns the {@link VariableResolver} for the given request.
      * <p>
-     *  If not resolver
-     * has yet be created for the requests, an instance of the
-     * {@link DefaultVariableResolver} is created, placed into the request and
-     * returned.
+     * If no resolver has yet be created for the requests, an instance of the
+     * {@link DefaultVariableResolver} is created with preset properties,
+     * placed into the request and returned. The preset properties are
+     * <code>appRoot</code> set to the value of the
+     * {@link WebConsoleConstants#ATTR_APP_ROOT} request attribute and
+     * <code>pluginRoot</code> set to the value of the
+     * {@link WebConsoleConstants#ATTR_PLUGIN_ROOT} request attribute.
      * <p>
      * <b>Note</b>: An object not implementing the {@link VariableResolver}
      * interface already stored as the
@@ -77,7 +80,9 @@
             return ( VariableResolver ) resolverObj;
         }
 
-        final VariableResolver resolver = new DefaultVariableResolver();
+        final DefaultVariableResolver resolver = new DefaultVariableResolver();
+        resolver.put( "appRoot", request.getAttribute( WebConsoleConstants.ATTR_APP_ROOT ) );
+        resolver.put( "pluginRoot", request.getAttribute( WebConsoleConstants.ATTR_PLUGIN_ROOT ) );
         setVariableResolver( request, resolver );
         return resolver;
     }
@@ -101,8 +106,8 @@
     /**
      * An utility method, that is used to filter out simple parameter from file
      * parameter when multipart transfer encoding is used.
-     * 
-     * This method processes the request and sets a request attribute 
+     *
+     * This method processes the request and sets a request attribute
      * {@link AbstractWebConsolePlugin#ATTR_FILEUPLOAD}. The attribute value is a {@link Map}
      * where the key is a String specifying the field name and the value
      * is a {@link org.apache.commons.fileupload.FileItem}.
@@ -186,12 +191,12 @@
      * Utility method to handle relative redirects.
      * Some application servers like Web Sphere handle relative redirects differently
      * therefore we should make an absolute URL before invoking send redirect.
-     * 
+     *
      * @param request the HTTP request coming from the user
      * @param response the HTTP response, where data is rendered
      * @param redirectUrl the redirect URI.
      * @throws IOException If an input or output exception occurs
-     * @throws IllegalStateException   If the response was committed or if a partial 
+     * @throws IllegalStateException   If the response was committed or if a partial
      *  URL is given and cannot be converted into a valid URL
      */
     public static final void sendRedirect(final HttpServletRequest request,
@@ -218,8 +223,8 @@
 
     /**
      * Escapes HTML special chars like: <>&\r\n and space
-     * 
-     * 
+     *
+     *
      * @param text the text to escape
      * @return the escaped text
      */
@@ -262,7 +267,7 @@
 
     /**
      * Retrieves a request parameter and converts it to int.
-     * 
+     *
      * @param request the HTTP request
      * @param name the name of the request parameter
      * @param _default the default value returned if the parameter is not set or is not a valid integer.
@@ -287,9 +292,9 @@
     }
 
     /**
-     * Writes a key-value pair in a JSON writer. Write is performed only if both key and 
+     * Writes a key-value pair in a JSON writer. Write is performed only if both key and
      * value are not null.
-     * 
+     *
      * @param jw the writer, where to write the data
      * @param key the key value, stored under 'key'
      * @param value the value stored under 'value'
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/system/VMStatPlugin.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/system/VMStatPlugin.java
index c71dcda..5b07923 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/system/VMStatPlugin.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/system/VMStatPlugin.java
@@ -20,51 +20,75 @@
 
 
 import java.io.IOException;
-import java.io.PrintWriter;
 import java.util.Date;
 
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.felix.webconsole.internal.BaseWebConsolePlugin;
-import org.apache.felix.webconsole.internal.Util;
-import org.apache.felix.webconsole.internal.core.SetStartLevelAction;
+import org.apache.commons.io.IOUtils;
+import org.apache.felix.webconsole.DefaultVariableResolver;
+import org.apache.felix.webconsole.SimpleWebConsolePlugin;
+import org.apache.felix.webconsole.WebConsoleUtil;
+import org.apache.felix.webconsole.internal.OsgiManagerPlugin;
+import org.json.JSONException;
+import org.json.JSONObject;
 import org.osgi.framework.Bundle;
 import org.osgi.framework.BundleException;
-import org.osgi.service.log.LogService;
+import org.osgi.service.startlevel.StartLevel;
 
 
-public class VMStatPlugin extends BaseWebConsolePlugin
+/**
+ * VMStatPlugin provides the System Information tab. This particular plugin uses
+ * more than one templates.
+ */
+public class VMStatPlugin extends SimpleWebConsolePlugin implements OsgiManagerPlugin
 {
 
-    public static final String LABEL = "vmstat";
-
-    public static final String TITLE = "System Information";
+    private static final String LABEL = "vmstat";
+    private static final String TITLE = "System Information";
+    private static final String CSS[] = null;
 
     private static final String ATTR_TERMINATED = "terminated";
 
     private static final String PARAM_SHUTDOWN_TIMER = "shutdown_timer";
     private static final String PARAM_SHUTDOWN_TYPE = "shutdown_type";
-
     private static final String PARAM_SHUTDOWN_TYPE_RESTART = "Restart";
-    private static final String PARAM_SHUTDOWN_TYPE_STOP = "Stop";
+    //private static final String PARAM_SHUTDOWN_TYPE_STOP = "Stop";
 
     private static final long startDate = ( new Date() ).getTime();
 
+    // from BaseWebConsolePlugin
+    private static String START_LEVEL_NAME = StartLevel.class.getName();
 
-    public String getLabel()
+    // templates
+    private final String TPL_VM_MAIN;
+    private final String TPL_VM_STOP;
+    private final String TPL_VM_RESTART;
+
+
+    /** Default constructor */
+    public VMStatPlugin()
     {
-        return LABEL;
+        super( LABEL, TITLE, CSS );
+        // load templates
+        try
+        {
+            TPL_VM_MAIN = IOUtils.toString( getClass().getResourceAsStream( "/templates/vmstat.html" ), "UTF-8" );
+            TPL_VM_STOP = IOUtils.toString( getClass().getResourceAsStream( "/templates/vmstat_stop.html" ), "UTF-8" );
+            TPL_VM_RESTART = IOUtils.toString( getClass().getResourceAsStream( "/templates/vmstat_restart.html" ),
+                "UTF-8" );
+        }
+        catch ( IOException e )
+        {
+            throw new RuntimeException( e.toString() );
+        }
     }
 
 
-    public String getTitle()
-    {
-        return TITLE;
-    }
-
-
+    /**
+     * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+     */
     protected void doPost( HttpServletRequest request, HttpServletResponse response ) throws ServletException,
         IOException
     {
@@ -75,6 +99,7 @@
             final boolean restart = PARAM_SHUTDOWN_TYPE_RESTART.equals( request.getParameter( PARAM_SHUTDOWN_TYPE ) );
 
             // simply terminate VM in case of shutdown :-)
+            final Bundle systemBundle = getBundleContext().getBundle( 0 );
             Thread t = new Thread( "Stopper" )
             {
                 public void run()
@@ -88,12 +113,11 @@
                         // ignore
                     }
 
-                    getLog().log( LogService.LOG_INFO, "Shutting down server now!" );
+                    log( "Shutting down server now!" );
 
                     // stopping bundle 0 (system bundle) stops the framework
                     try
                     {
-                        Bundle systemBundle = getBundleContext().getBundle( 0 );
                         if ( restart )
                         {
                             systemBundle.update();
@@ -105,7 +129,7 @@
                     }
                     catch ( BundleException be )
                     {
-                        getLog().log( LogService.LOG_ERROR, "Problem stopping or restarting the Framework", be );
+                        log( "Problem stopping or restarting the Framework", be );
                     }
                 }
             };
@@ -120,178 +144,70 @@
     }
 
 
+    /**
+     * @see org.apache.felix.webconsole.AbstractWebConsolePlugin#renderContent(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+     */
     protected void renderContent( HttpServletRequest request, HttpServletResponse response ) throws ServletException,
         IOException
     {
-        PrintWriter pw = response.getWriter();
-
-        pw.println( "" );
+        String body;
 
         if ( request.getAttribute( ATTR_TERMINATED ) != null )
         {
-            pw.println( "<tr>" );
-            pw.println( "<td colspan='2' class='techcontentcell'>" );
-            pw.println( "<table class='content' cellpadding='0' cellspacing='0' width='100%'>" );
-            pw.println( "<tr class='content'>" );
-
             Object restart = request.getAttribute( PARAM_SHUTDOWN_TYPE );
             if ( ( restart instanceof Boolean ) && ( ( Boolean ) restart ).booleanValue() )
             {
-                pw.println( "<th class='content important'>Framework is restarting. stand by ...</th>" );
-
-                pw.println( "<td class='content'>" );
-                pw.println( "<form name='reloadform' method='get'>" );
-                pw.println( "<input class='submit important' type='submit' value='Reload')\">&nbsp;" );
-                pw.println( "Reloading in <span id='reloadcountdowncell'>&nbsp;</span>" );
-                pw.println( "<script language='JavaScript'>" );
-                pw.println( "shutdown(10, 'reloadform', 'reloadcountdowncell');" );
-                pw.println( "</script>" );
-
-                pw.println( "</form>" );
-                pw.println( "</td" );
+                body = TPL_VM_RESTART;
             }
             else
             {
-                pw.println( "<th class='content important'>Framework has been stopped.</th>" );
+                body = TPL_VM_STOP;
             }
-
-            pw.println( "</tr>" );
-            pw.println( "</table>" );
-            pw.println( "</td>" );
-            pw.println( "</tr>" );
+            response.getWriter().print( body );
             return;
         }
 
-        boolean shutdownTimer = false;
-        String target = request.getRequestURI();
-        if ( request.getParameter( PARAM_SHUTDOWN_TIMER ) != null )
-        {
-            target = getLabel(); // ShutdownRender.NAME;
-            shutdownTimer = true;
-        }
-
-        pw.println( "<table class='content' cellpadding='0' cellspacing='0' width='100%'>" );
-
-        pw.println( "<tr class='content'>" );
-        pw.println( "<th colspan='2' class='content container'>Start Level Information:</th>" );
-        pw.println( "</tr>" );
-
-        pw.println( "<tr class='content'>" );
-        pw.println( "<td class='content'>System Start Level</td>" );
-        pw.println( "<td class='content'>" );
-        pw.println( "<form method='post'>" );
-        pw.println( "<input type='hidden' name='" + Util.PARAM_ACTION + "' value='" + SetStartLevelAction.NAME + "'>" );
-        pw.println( "<input class='input' type='text' size='3' name='systemStartLevel' value='"
-            + getStartLevel().getStartLevel() + "'/>" );
-        pw.println( "&nbsp;&nbsp;<input class='submit' type='submit' name='" + SetStartLevelAction.LABEL
-            + "' value='Change'>" );
-        pw.println( "</form>" );
-        pw.println( "</td>" );
-        pw.println( "</tr>" );
-        pw.println( "<tr class='content'>" );
-        pw.println( "<td class='content'>Default Bundle Start Level</td>" );
-        pw.println( "<td class='content'>" );
-        pw.println( "<form method='post'>" );
-        pw.println( "<input type='hidden' name='" + Util.PARAM_ACTION + "' value='" + SetStartLevelAction.NAME + "'>" );
-        pw.println( "<input class='input' type='text' size='3' name='bundleStartLevel' value='"
-            + getStartLevel().getInitialBundleStartLevel() + "'/>" );
-        pw.println( "&nbsp;&nbsp;<input class='submit' type='submit' name='" + SetStartLevelAction.LABEL
-            + "' value='Change'>" );
-        pw.println( "</form>" );
-        pw.println( "</td>" );
-        pw.println( "</tr>" );
-
-        pw.println( "<tr class='content'>" );
-        pw.println( "<td colspan='2' class='content'>&nbsp;</th>" );
-        pw.println( "</tr>" );
-
-        pw.println( "<tr class='content'>" );
-        pw.println( "<th colspan='2' class='content container'>Server Information:</th>" );
-        pw.println( "</tr>" );
-
-        pw.println( "<tr class='content'>" );
-        pw.println( "<td class='content'>Last Started</td>" );
-        pw.println( "<td class='content'>" );
-        pw.println( "<script language='JavaScript'>" );
-        pw.println( "localDate(" + startDate /* <%= Server.getStartTime() %> */
-            + ")" );
-        pw.println( "</script>" );
-        pw.println( "</td>" );
-        pw.println( "</tr>" );
-
-        pw.println( "<tr class='content'>" );
-        pw.println( "<form name='shutdownform' method='post' action='" + target + "'>" );
-        pw.println( "<td class='content'>Framework</td>" );
-        pw.println( "<td class='content'>" );
-
-        if ( !shutdownTimer )
-        {
-            pw.println( "<input type='hidden' name='" + PARAM_SHUTDOWN_TIMER + "' value='" + PARAM_SHUTDOWN_TIMER
-                + "'>" );
-            pw
-                .println( "<input class='submit important' type='submit' name='"
-                    + PARAM_SHUTDOWN_TYPE
-                    + "' value='Restart' onclick=\"return confirm('This will stop and restart the framework and all bundles. Please confirm to continue.')\">" );
-            pw
-                .println( "<input class='submit important' type='submit' name='"
-                    + PARAM_SHUTDOWN_TYPE
-                    + "' value='Stop' onclick=\"return confirm('This will stop the framework and all bundles. Please confirm to continue.')\">" );
-        }
-        else
-        {
-            pw.println( "<input type='hidden' name='" + PARAM_SHUTDOWN_TYPE + "' value='"
-                + request.getParameter( PARAM_SHUTDOWN_TYPE ) + "'>" );
-            pw.println( "<input class='submit important' type='button' value='Abort' onclick=\"abort('"
-                + request.getRequestURI() + "')\">&nbsp;" );
-            pw.println( "Shutdown in <span id='countdowncell'>&nbsp;</span>" );
-            pw.println( "<script language='JavaScript'>" );
-            pw.println( "shutdown(3, 'shutdownform', 'countdowncell');" );
-            pw.println( "</script>" );
-        }
-
-        pw.println( "</td>" );
-        pw.println( "</form>" );
-        pw.println( "</tr>" );
-
-        pw.println( "<tr class='content'>" );
-        pw.println( "<td colspan='2' class='content'>&nbsp;</th>" );
-        pw.println( "</tr>" );
-
-        pw.println( "<tr class='content'>" );
-        pw.println( "<th colspan='2' class='content container'>Java Information:</th>" );
-        pw.println( "</tr>" );
+        body = TPL_VM_MAIN;
 
         long freeMem = Runtime.getRuntime().freeMemory() / 1024;
         long totalMem = Runtime.getRuntime().totalMemory() / 1024;
         long usedMem = totalMem - freeMem;
 
-        this.infoLine( pw, "Java Runtime", System.getProperty( "java.runtime.name" ) + "(build "
-            + System.getProperty( "java.runtime.version" ) + ")" );
-        this.infoLine( pw, "Java Virtual Machine", System.getProperty( "java.vm.name" ) + "(build "
-            + System.getProperty( "java.vm.version" ) + ", " + System.getProperty( "java.vm.info" ) + ")" );
-        this.infoLine( pw, "Total Memory", totalMem + " KB" );
-        this.infoLine( pw, "Used Memory", usedMem + " KB" );
-        this.infoLine( pw, "Free Memory", freeMem + " KB" );
+        boolean shutdownTimer = request.getParameter( PARAM_SHUTDOWN_TIMER ) != null;
+        String shutdownType = request.getParameter( PARAM_SHUTDOWN_TYPE );
+        if ( shutdownType == null )
+            shutdownType = "";
 
-        pw.println( "<tr class='content'>" );
-        pw.println( "<form method='post'>" );
-        pw.println( "<td class='content'>Garbage Collection</td>" );
-        pw.println( "<td class='content'>" );
-        pw.println( "<input type='hidden' name='" + Util.PARAM_ACTION + "' value='" + GCAction.NAME + "'>" );
-        pw.println( "<input class='submit' type='submit' name='" + GCAction.LABEL + "' value='Run'>" );
-        pw.println( "</form></td></tr>" );
+        JSONObject json = new JSONObject();
+        try
+        {
+            json.put( "systemStartLevel", getStartLevel().getStartLevel() );
+            json.put( "bundleStartLevel", getStartLevel().getInitialBundleStartLevel() );
+            json.put( "lastStarted", startDate );
+            json.put( "runtime", System.getProperty( "java.runtime.name" ) + "(build "
+                + System.getProperty( "java.runtime.version" ) + ")" );
+            json.put( "jvm", System.getProperty( "java.vm.name" ) + "(build " + System.getProperty( "java.vm.version" )
+                + ", " + System.getProperty( "java.vm.info" ) + ")" );
+            json.put( "shutdownTimer", shutdownTimer );
+            json.put( "mem_total", totalMem );
+            json.put( "mem_free", freeMem );
+            json.put( "mem_used", usedMem );
+            json.put( "shutdownType", shutdownType );
+        }
+        catch ( JSONException e )
+        {
+            throw new IOException( e.toString() );
+        }
 
-        pw.println( "</table>" );
+        DefaultVariableResolver vars = ( ( DefaultVariableResolver ) WebConsoleUtil.getVariableResolver( request ) );
+        vars.put( "startData", json.toString() );
+
+        response.getWriter().print( body );
     }
 
 
-    private void infoLine( PrintWriter pw, String label, String value )
+    private final StartLevel getStartLevel()
     {
-        pw.println( "<tr class='content'>" );
-        pw.println( "<td class='content'>" + label + "</td>" );
-        pw.println( "<td class='content'>" );
-        pw.println( value );
-        pw.println( "</td></tr>" );
+        return ( StartLevel ) getService( START_LEVEL_NAME );
     }
-
 }
diff --git a/webconsole/src/main/resources/OSGI-INF/l10n/bundle.properties b/webconsole/src/main/resources/OSGI-INF/l10n/bundle.properties
index ebd5908..273811f 100644
--- a/webconsole/src/main/resources/OSGI-INF/l10n/bundle.properties
+++ b/webconsole/src/main/resources/OSGI-INF/l10n/bundle.properties
@@ -23,9 +23,31 @@
 # to translate the natively encoded files to ISO-8859-1 during bundle build
 #
 
-#
-# There are no resources currently.
-#
-# In the future, this file will list the keys used in the Web Console bundle,
-# which may be translated by localization fragments.
-#
+
+# Common UI
+reload=Reload
+change=Change
+abort=Abort
+
+# VMStat plugin
+vmstat.stopped=Framework has been stopped.
+vmstat.restarting=Framework is restarting. stand by ...
+vmstat.reloading.in=Reloading in
+vmstat.running=System is up and running!
+vmstat.sl.title=Start Level Information:
+vmstat.sl.system=System Start Level
+vmstat.sl.bundle=Default Bundle Start Level
+vmstat.info.title=Server Information:
+vmstat.lastStarted=Last Started
+vmstat.framework=Framework
+vmstat.shutdown.in=Shutdown in 
+vmstat.java.title=Java Information:
+vmstat.java.runtime=Java Runtime
+vmstat.java.jvm=Java Virtual Machine
+vmstat.mem.total=Total Memory
+vmstat.mem.used=Used Memory
+vmstat.mem.free=Free Memory
+vmstat.gc.title=Garbage Collection
+vmstat.gc.button=Run
+
+
diff --git a/webconsole/src/main/resources/res/ui/vmstat.js b/webconsole/src/main/resources/res/ui/vmstat.js
new file mode 100644
index 0000000..684b68a
--- /dev/null
+++ b/webconsole/src/main/resources/res/ui/vmstat.js
@@ -0,0 +1,42 @@
+/* shuts down server after [num] seconds */
+function shutdown(num, formname, elemid) {
+	var elem = $('#' + elemid);
+	var secs=" second";
+	var ellipsis="...";
+	if (num > 0) {
+		if (num != 1) {
+			secs+="s";
+		}
+	    elem.html(num+secs+ellipsis);
+		setTimeout('shutdown('+(--num)+', "'+formname+'", "'+elemid+'")',1000);
+	} else {
+	    $('#' + formname).submit();
+	}
+}
+
+/* aborts server shutdown and redirects to [target] */
+function abort(target) {
+    top.location.href=target;
+}
+
+/* displays a date in the user's local timezone */
+function localTm(time) {
+	return (time ? new Date(time) : new Date()).toLocaleString();
+}
+/* fill in the data */
+$(document).ready(function() {
+	if(typeof statData == 'undefined') return;
+	for(i in statData) {
+		var target = $('#' + i);
+		if (target.val()) {
+			target.val(statData[i]);
+		} else {
+			target.text(statData[i]);
+		}
+	}
+	$('#lastStarted').text(localTm(statData.lastStarted));
+	var st = statData.shutdownTimer;
+	$('#shutdownform').css('display', st ? 'none' : 'block');
+	$('#shutdownform2').css('display', st ? 'block' : 'none');
+	$('#shutdown_type').val(statData.shutdownType);
+});
\ No newline at end of file
diff --git a/webconsole/src/main/resources/templates/vmstat.html b/webconsole/src/main/resources/templates/vmstat.html
new file mode 100644
index 0000000..bf1d09a
--- /dev/null
+++ b/webconsole/src/main/resources/templates/vmstat.html
@@ -0,0 +1,108 @@
+<script type="text/javascript" src="res/ui/vmstat.js"></script>
+<script type="text/javascript">
+// <![CDATA[
+var statData = ${startData};
+// ]]>
+</script>
+
+<!-- status line -->
+<p class="statline">${vmstat.running}</p>
+
+<table class="nicetable">
+	<thead>
+		<tr>
+			<th colspan="2">${vmstat.sl.title}</th>
+		</tr>
+	</thead>
+
+	<tr>
+		<td>${vmstat.sl.system}</td>
+		<td>
+			<form method="post" action="${pluginRoot}">
+				<div>
+					<input type="hidden" name="action" value="setStartLevel"/>
+					<input type="text" size="3" name="systemStartLevel" id="systemStartLevel" value="-1"/>
+					&nbsp;&nbsp;<input type="submit" name="Set Start Level" value="${change}"/>
+				</div>
+			</form>
+		</td>
+	</tr>
+	<tr>
+		<td>${vmstat.sl.bundle}</td>
+		<td>
+			<form method="post" action="${pluginRoot}">
+				<div>
+					<input type="hidden" name="action" value="setStartLevel"/>
+					<input type="text" size="3" name="bundleStartLevel" id="bundleStartLevel" value="-1"/>
+					&nbsp;&nbsp;<input type="submit" name="Set Start Level" value="${change}"/>
+				</div>
+			</form>
+		</td>
+	</tr>
+
+	<tr><td colspan="2">&nbsp;</td></tr>
+	<tr>
+		<th colspan="2">${vmstat.info.title}</th>
+	</tr>
+	<tr>
+		<td>${vmstat.lastStarted}</td>
+		<td id="lastStarted">---</td>
+	</tr>
+	<tr>
+		<td>${vmstat.framework}</td>
+		<td>
+			<form id="shutdownform" method="post" action="${pluginRoot}">
+				<div>
+				<input type="hidden" name="shutdown_timer" value="shutdown_timer" />
+				<!-- NOTE: don't translate value="Restart" & value="Stop" - will break the operation type -->
+				<input class="ui-state-error" type="submit" name="shutdown_type" value="Restart" onclick="return confirm('This will stop and restart the framework and all bundles. Please confirm to continue.');" />
+				<input class="ui-state-error" type="submit" name="shutdown_type" value="Stop" onclick="return confirm('This will stop the framework and all bundles. Please confirm to continue.')" />
+				</div>
+			</form>
+			<form id="shutdownform2" method="post" action="${pluginRoot}">
+				<div>
+				<input type="hidden" name="shutdown_type" id="shutdown_type" value="" />
+				<input class="ui-state-error" type="button" value="${abort}" onclick="abort('${pluginRoot}')" />
+				${vmstat.shutdown.in} <span id='countdowncell'>&nbsp;</span>
+				<script type="text/javascript">if(statData.shutdownTimer) shutdown(3, 'shutdownform2', 'countdowncell');</script>
+				</div>
+			</form>
+		</td>
+	</tr>
+
+	<tr><td colspan="2">&nbsp;</td></tr>
+	<tr>
+		<th colspan="2">${vmstat.java.title}</th>
+	</tr>
+	<tr>
+		<td>${vmstat.java.runtime}</td>
+		<td id="runtime">-</td>
+	</tr>
+	<tr>
+		<td>${vmstat.java.jvm}</td>
+		<td id="jvm">-</td>
+	</tr>
+	<tr>
+		<td>${vmstat.mem.total}</td>
+		<td id="mem_total">-</td>
+	</tr>
+	<tr>
+		<td>${vmstat.mem.used}</td>
+		<td id="mem_used">-</td>
+	</tr>
+	<tr>
+		<td>${vmstat.mem.free}</td>
+		<td id="mem_free">-</td>
+	</tr>
+	<tr>
+		<td>${vmstat.gc.title}</td>
+		<td>
+			<form method="post" action="${pluginRoot}">
+				<div>
+					<input type="hidden" name="action" value="gc" />
+					<input class="submit" type="submit" name="Collect Garbage" value="${vmstat.gc.button}" />
+				</div>
+			</form>
+		</td>
+	</tr>
+</table>
diff --git a/webconsole/src/main/resources/templates/vmstat_restart.html b/webconsole/src/main/resources/templates/vmstat_restart.html
new file mode 100644
index 0000000..bb1f933
--- /dev/null
+++ b/webconsole/src/main/resources/templates/vmstat_restart.html
@@ -0,0 +1,13 @@
+<script type="text/javascript" src="res/ui/vmstat.js"></script>
+
+<!-- status line -->
+<p class="statline">${vmstat.restarting}</p>
+
+<form id="reloadform" method="get" action="">
+	<div style="width:100%; text-align: center">
+		<input class="ui-state-error" type="submit" value="${reload}" />
+		${vmstat.reloading.in} <span id="reloadcountdowncell">&nbsp;</span>
+		<script type="text/javascript">shutdown(10, "reloadform", "reloadcountdowncell");</script>
+	</div>
+</form>
+
diff --git a/webconsole/src/main/resources/templates/vmstat_stop.html b/webconsole/src/main/resources/templates/vmstat_stop.html
new file mode 100644
index 0000000..ce054c2
--- /dev/null
+++ b/webconsole/src/main/resources/templates/vmstat_stop.html
@@ -0,0 +1,5 @@
+<script type="text/javascript" src="res/ui/vmstat.js"></script>
+
+<!-- status line -->
+<p class="statline">${vmstat.stopped}</p>
+