FELIX-1988 Apply 11.shell_plugin.patch by Valentin Valchev (thanks)

git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@911382 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/webconsole/src/main/java/org/apache/felix/webconsole/internal/misc/ShellServlet.java b/webconsole/src/main/java/org/apache/felix/webconsole/internal/misc/ShellServlet.java
index 36d5bad..e4aecdf 100644
--- a/webconsole/src/main/java/org/apache/felix/webconsole/internal/misc/ShellServlet.java
+++ b/webconsole/src/main/java/org/apache/felix/webconsole/internal/misc/ShellServlet.java
@@ -30,35 +30,38 @@
 import javax.servlet.http.HttpServletResponse;
 
 import org.apache.felix.shell.ShellService;
-import org.apache.felix.webconsole.AbstractWebConsolePlugin;
-import org.apache.felix.webconsole.WebConsoleConstants;
+import org.apache.felix.webconsole.SimpleWebConsolePlugin;
 import org.apache.felix.webconsole.WebConsoleUtil;
 import org.apache.felix.webconsole.internal.OsgiManagerPlugin;
-import org.apache.felix.webconsole.internal.Util;
-import org.osgi.framework.BundleContext;
-import org.osgi.util.tracker.ServiceTracker;
 
 
-public class ShellServlet extends AbstractWebConsolePlugin implements OsgiManagerPlugin
+/**
+ * ShellServlet provides a Web bases interface to the Apache shell service, allowing
+ * the user to execute shell commands from the browser.
+ */
+public class ShellServlet extends SimpleWebConsolePlugin implements OsgiManagerPlugin
 {
-    private static final String[] CSS_REFS =
-        { "res/ui/shell.css" };
 
-    private ServiceTracker shellTracker;
+    private static final String LABEL = "shell";
+    private static final String TITLE = "Shell";
+    private static final String[] CSS = { "/res/ui/shell.css" };
+    
+    // templates
+    private final String TEMPLATE;
 
-
-    public String getLabel()
+    /** Default constructor */
+    public ShellServlet()
     {
-        return "shell";
+        super(LABEL, TITLE, CSS);
+
+        // load templates
+        TEMPLATE = readTemplateFile( "/templates/shell.html" ); 
     }
 
 
-    public String getTitle()
-    {
-        return "Shell";
-    }
-
-
+    /**
+     * @see javax.servlet.http.HttpServlet#doPost(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+     */
     protected void doPost( HttpServletRequest request, HttpServletResponse response ) throws ServletException,
         IOException
     {
@@ -114,73 +117,18 @@
         }
     }
 
-
-    protected String[] getCssReferences()
-    {
-        return CSS_REFS;
-    }
-
-
+    /**
+     * @see org.apache.felix.webconsole.AbstractWebConsolePlugin#renderContent(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
+     */
     protected void renderContent( HttpServletRequest request, HttpServletResponse response ) throws IOException
     {
-        PrintWriter pw = response.getWriter();
-
-        final String appRoot = ( String ) request.getAttribute( WebConsoleConstants.ATTR_APP_ROOT );
-        Util.script( pw, appRoot, "shell.js" );
-
-        pw.println( "<br />" );
-
-        pw.println( "<form name=\"shellCommandForm\" method=\"post\" action=\"" + appRoot
-            + "/shell\" title=\"Shell Command\" onsubmit=\"runShellCommand();return false;\">" );
-
-        pw.println( "<div class=\"consolebuttons\">" );
-        pw.println( "<input class=\"submit\" type=\"button\" value=\"Help\" onclick=\"executeCommand('help');\"/>" );
-        pw
-            .println( "&nbsp;&nbsp;<input class=\"submit\" type=\"button\" value=\"Clear\" onclick=\"clearConsole();\"/>" );
-        pw.println( "</div>" );
-
-        pw.println( "<div id=\"consoleframe\" class=\"consoleframe\" onclick=\"shellCommandFocus();\">" );
-        pw.println( "<div id=\"console\" class=\"console\" onclick=\"shellCommandFocus();\">" );
-        pw.println( "</div>" );
-
-        pw.println( "<span class=\"prompt\">" );
-        pw.println( "-&gt; <input type=\"text\" name=\"command\" value=\"\" class=\"command\" autocomplete=\"off\"/>" );
-        pw.println( "</span>" );
-
-        pw.println( "</div>" );
-
-        pw.println( "</form>" );
-
-        pw.println( "<script type=\"text/javascript\">" );
-        pw.println( "shellCommandFocus();" );
-        pw.println( "</script>" );
+        response.getWriter().print(TEMPLATE);
     }
 
 
-    protected ShellService getShellService()
+    private final ShellService getShellService()
     {
-        return ( ( ShellService ) shellTracker.getService() );
-    }
-
-
-    public void activate( BundleContext bundleContext )
-    {
-        super.activate( bundleContext );
-
-        shellTracker = new ServiceTracker( bundleContext, ShellService.class.getName(), null );
-        shellTracker.open();
-    }
-
-
-    public void deactivate()
-    {
-        if ( shellTracker != null )
-        {
-            shellTracker.close();
-            shellTracker = null;
-        }
-
-        super.deactivate();
+        return ((ShellService) getService(ShellService.class.getName()));
     }
 
 }
diff --git a/webconsole/src/main/resources/res/ui/shell.css b/webconsole/src/main/resources/res/ui/shell.css
index 111f8c0..e164930 100644
--- a/webconsole/src/main/resources/res/ui/shell.css
+++ b/webconsole/src/main/resources/res/ui/shell.css
@@ -15,50 +15,23 @@
  * limitations under the License.
  */
 
-div.consolebuttons {
-    text-align: right;
-    border: none;
-    width: 955px;
-    padding-bottom: 2px;
-}
-
-div.consoleframe {
-    font-family: "Courier New", Courier, monospace;
-    font-size: 12px;
-    font-weight: normal;
+#consoleframe {
+    font-family: monospace;
     background-color: #f0f0f0;
-    color: #000000;
-    border: 1px solid #999999;
-    width: 955px;
     height: 500px;
     overflow: auto;
 }
 
-div.console {
-}
-
 span.consolecommand {
     white-space: pre;
+	font-weight: bold;
 }
 
 span.error {
     color: #ff0000;
 }
 
-span.prompt {
-    padding-left: 0px;
-    padding-top: 2px;
-    padding-bottom: 3px;
-}
-
 input.command {
-    font-family: "Courier New", Courier, monospace;
-    font-size: 12px;
-    font-weight: normal;
-    background-color: #f0f0f0;
-    color: #000000;
-    border: none;
-    width: 900px;
-    margin-left: -1px; 
-    margin-top: -1px; 
+    font-family: monospace;
+    width: 80%;
 }
diff --git a/webconsole/src/main/resources/res/ui/shell.js b/webconsole/src/main/resources/res/ui/shell.js
index a36257c..8a79c8e 100644
--- a/webconsole/src/main/resources/res/ui/shell.js
+++ b/webconsole/src/main/resources/res/ui/shell.js
@@ -15,72 +15,41 @@
  * limitations under the License.
  */
 
-function executeCommand(command) {
-    var xmlhttp = getXmlHttp();
-    if (!xmlhttp) {
-        return;
-    }
-    
-    if (xmlhttp.readyState < 4) {
-        xmlhttp.abort();
-    }
-    
-    var url = document.location;
-    
-    xmlhttp.open("POST", url);
-    
-    // set If-Modified-Since way back in the past to prevent
-    // using any content from the cache
-    xmlhttp.setRequestHeader("If-Modified-Since", new Date(0));
-    xmlhttp.setRequestHeader("Content-Type","application/x-www-form-urlencoded");
-    
-    xmlhttp.onreadystatechange = updateConsole;
-    
-    xmlhttp.send("command=" + encodeURIComponent(command));
+// elements cache
+var consoleframe = false;
+var console = false;
+var command = false;
+
+function executeCommand(cmd) {
+	$.post(document.location.href, { 'command' : encodeURIComponent(cmd) },
+		function(result) {
+			console.removeClass('ui-helper-hidden').append(result);
+			consoleframe.attr('scrollTop', console.attr('scrollHeight'));
+			command.val('');
+			shellCommandFocus();
+		}, 'html');
 }
 
-function updateConsole() {
-    var xmlhttp = getXmlHttp();
-    if (!xmlhttp || xmlhttp.readyState != 4) {
-        return;
-    }
-    
-    var result = xmlhttp.responseText;
-    if (!result) {
-        return;
-    }
+function shellCommandFocus() { command.focus() }
 
-    var console = document.getElementById("console");
-    
-    console.style.display = "";
-    console.innerHTML = console.innerHTML + result;
-    
-    var consoleframe = document.getElementById("consoleframe");
-    consoleframe.scrollTop = console.scrollHeight;
+// automatically executed on load
+$(document).ready(function(){
+	// init cache
+	consoleframe = $('#consoleframe').click(shellCommandFocus);
+	console      = $('#console');
+	command      = $('#command').focus();
 
-    document.forms["shellCommandForm"].elements["command"].value = "";
-    
-    shellCommandFocus();
-}
-
-function clearConsole() {
-    var console = document.getElementById("console");
-
-    console.style.display = "none";
-    console.innerHTML = "";
-    
-    var consoleframe = document.getElementById("consoleframe");
-    consoleframe.scrollTop = 0;
-    
-    shellCommandFocus();
-}
-
-function shellCommandFocus() {
-    document.forms["shellCommandForm"].elements["command"].focus();
-}
-
-function runShellCommand() {
-    var command = document.forms["shellCommandForm"].elements["command"].value;
-    
-    executeCommand(command);
-}
+	// attach action handlers
+	$('#clear').click(function() {
+		console.addClass('ui-helper-hidden').html('');
+		consoleframe.attr('scrollTop', 0);
+		shellCommandFocus();
+	});
+	$('#help').click(function() {
+		executeCommand('help');
+	});
+	$('form').submit(function() {
+		executeCommand(command.val());
+		return false;
+	});
+});
diff --git a/webconsole/src/main/resources/templates/shell.html b/webconsole/src/main/resources/templates/shell.html
new file mode 100644
index 0000000..9a648a4
--- /dev/null
+++ b/webconsole/src/main/resources/templates/shell.html
@@ -0,0 +1,23 @@
+<script type="text/javascript" src="res/ui/shell.js"></script>
+
+<p class="statline">${shell.status}</p>
+
+<form method="post" action="${pluginRoot}">
+	<!-- top header -->
+	<div class="ui-widget-header ui-corner-top buttonGroup">
+		<input id="help" value="${help}" type="button" />
+		<input id="clear" value="${shell.clear}" type="button" />
+	</div>
+
+	<!-- the console window -->
+	<div id="consoleframe">
+		<div id="console">
+			<!-- HERE COMES CONSOLE CONTENTS -->
+		</div><!-- console -->
+	</div><!-- consoleframe -->
+
+	<!-- bottom header -->
+	<div class="ui-widget-header ui-corner-bottom buttonGroup" style="text-align: left">
+		&nbsp;-&gt; <input id="command" name="command" class="command" autocomplete="off" type="text" />
+	</div>
+</form>