FELIX-2625 First shot at creating a Gogo Shell Plugin for the Web Console
git-svn-id: https://svn.apache.org/repos/asf/felix/trunk@1238456 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/webconsole-plugins/gogo/src/main/resources/res/ui/gogo.css b/webconsole-plugins/gogo/src/main/resources/res/ui/gogo.css
new file mode 100644
index 0000000..f693de7
--- /dev/null
+++ b/webconsole-plugins/gogo/src/main/resources/res/ui/gogo.css
@@ -0,0 +1,91 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Based on http://antony.lesuisse.org/software/ajaxterm/
+ * Public Domain License
+ */
+
+div#console {
+ font-size: 12px;
+ margin: 12px;
+}
+
+div#term {
+ display: inline-block;
+}
+
+pre.stat {
+ margin: 0px;
+ padding: 4px;
+ display: block;
+ font-family: monospace;
+ white-space: pre;
+ background-color: black;
+ border-top: 1px solid black;
+ color: white;
+}
+pre.stat span {
+ padding: 0px;
+}
+pre.stat .on {
+ background-color: #080;
+ font-weight: bold;
+ color: white;
+ cursor: pointer;
+}
+pre.stat .off {
+ background-color: #888;
+ font-weight: bold;
+ color: white;
+ cursor: pointer;
+}
+pre.term {
+ margin: 0px;
+ padding: 4px;
+ display: block;
+ font-family: monospace;
+ white-space: pre;
+ background:#000;
+ border-top: 1px solid white;
+ color: #eee;
+}
+pre.term span.f0 { color: #000000; }
+pre.term span.f1 { color: #c00006; }
+pre.term span.f2 { color: #1bc806; }
+pre.term span.f3 { color: #c3c609; }
+pre.term span.f4 { color: #0000c2; }
+pre.term span.f5 { color: #bf00c2; }
+pre.term span.f6 { color: #19c4c2; }
+pre.term span.f7 { color: #f2f2f2; }
+pre.term span.f12 { color: transparent; }
+pre.term span.f14 { color: #000000; }
+pre.term span.f15 { color: #bbbbbb; }
+pre.term span.b0 { background-color: #000000; }
+pre.term span.b1 { background-color: #cc2300; }
+pre.term span.b2 { background-color: #00cc00; }
+pre.term span.b3 { background-color: #cccc00; }
+pre.term span.b4 { background-color: #0e2acc; }
+pre.term span.b5 { background-color: #cc34cc; }
+pre.term span.b6 { background-color: #00cccc; }
+pre.term span.b7 { background-color: #f5f5f5; }
+pre.term span.b12 { background-color: #555555; }
+pre.term span.b14 { background-color: transparent; }
+pre.term span.b15 { background-color: #ffffff; }
+pre.term span.ul { text-decoration: underline; }
+pre.term span.b { font-weight:900; }
+
diff --git a/webconsole-plugins/gogo/src/main/resources/res/ui/gogo.js b/webconsole-plugins/gogo/src/main/resources/res/ui/gogo.js
new file mode 100644
index 0000000..77044a7
--- /dev/null
+++ b/webconsole-plugins/gogo/src/main/resources/res/ui/gogo.js
@@ -0,0 +1,245 @@
+//
+// Licensed to the Apache Software Foundation (ASF) under one or more
+// contributor license agreements. See the NOTICE file distributed with
+// this work for additional information regarding copyright ownership.
+// The ASF licenses this file to You under the Apache License, Version 2.0
+// (the "License"); you may not use this file except in compliance with
+// the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+//
+// Based on http://antony.lesuisse.org/software/ajaxterm/
+// Public Domain License
+//
+
+gogo = { };
+
+gogo.Terminal_ctor = function(div, width, height) {
+
+ var query0 = "w=" + width + "&h=" + height;
+ var query1 = query0 + "&k=";
+ var buf = "";
+ var timeout;
+ var error_timeout;
+ var keybuf = [];
+ var sending = 0;
+ var rmax = 1;
+ var force = 1;
+
+ var dstat = document.createElement('pre');
+ var sled = document.createElement('span');
+ var sdebug = document.createElement('span');
+ var dterm = document.createElement('div');
+
+ function debug(s) {
+ sdebug.innerHTML = s;
+ }
+
+ function error() {
+ sled.className = 'off';
+ debug("Connection lost timeout ts:" + ((new Date).getTime()));
+ }
+
+ function update() {
+ if (sending == 0) {
+ sending = 1;
+ sled.className = 'on';
+ var r = new XMLHttpRequest();
+ var send = "";
+ while (keybuf.length > 0) {
+ send += keybuf.pop();
+ }
+ var query = query1 + send;
+ if (force) {
+ query = query + "&f=1";
+ force = 0;
+ }
+ r.open("POST", "gogo", true);
+ r.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
+ r.onreadystatechange = function () {
+ if (r.readyState == 4) {
+ if (r.status == 200) {
+ window.clearTimeout(error_timeout);
+ if (r.responseText.length > 0) {
+ dterm.innerHTML = r.responseText;
+ rmax = 100;
+ } else {
+ rmax *= 2;
+ if (rmax > 2000)
+ rmax = 2000;
+ }
+ sending=0;
+ sled.className = 'off';
+ timeout = window.setTimeout(update, rmax);
+ } else {
+ debug("Connection error status:" + r.status);
+ }
+ }
+ }
+ error_timeout = window.setTimeout(error, 5000);
+ r.send(query);
+ }
+ }
+
+ function queue(s) {
+ keybuf.unshift(s);
+ if (sending == 0) {
+ window.clearTimeout(timeout);
+ timeout = window.setTimeout(update, 1);
+ }
+ }
+
+ function keypress(ev, fromkeydown) {
+ // Translate to standard keycodes
+ if (!ev)
+ ev = window.event;
+ var kc;
+ if (ev.keyCode)
+ kc = ev.keyCode;
+ if (!fromkeydown && ev.which)
+ kc = ev.which;
+ if (ev.ctrlKey) {
+ if (kc >= 0 && kc <= 32)
+ kc = kc;
+ else if (kc >= 65 && kc <= 90)
+ kc -= 64;
+ else if (kc >= 97 && kc <= 122)
+ kc -= 96;
+ else {
+ switch (kc) {
+ case 54: kc=30; break; // Ctrl-^
+ case 109: kc=31; break; // Ctrl-_
+ case 219: kc=27; break; // Ctrl-[
+ case 220: kc=28; break; // Ctrl-\
+ case 221: kc=29; break; // Ctrl-]
+ default: return true;
+ }
+ }
+ } else if (fromkeydown) {
+ switch(kc) {
+ case 8: break; // Backspace
+ case 9: break; // Tab
+ case 27: break; // ESC
+ case 33: kc = 63276; break; // PgUp
+ case 34: kc = 63277; break; // PgDn
+ case 35: kc = 63275; break; // End
+ case 36: kc = 63273; break; // Home
+ case 37: kc = 63234; break; // Left
+ case 38: kc = 63232; break; // Up
+ case 39: kc = 63235; break; // Right
+ case 40: kc = 63233; break; // Down
+ case 45: kc = 63302; break; // Ins
+ case 46: kc = 63272; break; // Del
+ case 112: kc = 63236; break; // F1
+ case 113: kc = 63237; break; // F2
+ case 114: kc = 63238; break; // F3
+ case 115: kc = 63239; break; // F4
+ case 116: kc = 63240; break; // F5
+ case 117: kc = 63241; break; // F6
+ case 118: kc = 63242; break; // F7
+ case 119: kc = 63243; break; // F8
+ case 120: kc = 63244; break; // F9
+ case 121: kc = 63245; break; // F10
+ case 122: kc = 63246; break; // F11
+ case 123: kc = 63247; break; // F12
+ default: return true;
+ }
+ }
+
+ var k = "";
+ // Build character
+ switch (kc) {
+ case 126: k = "~~"; break;
+ case 63232: k = "~A"; break; // Up
+ case 63233: k = "~B"; break; // Down
+ case 63234: k = "~D"; break; // Left
+ case 63235: k = "~C"; break; // Right
+ case 63276: k = "~1"; break; // PgUp
+ case 63277: k = "~2"; break; // PgDn
+ case 63273: k = "~H"; break; // Home
+ case 63275: k = "~F"; break; // End
+ case 63302: k = "~3"; break; // Ins
+ case 63272: k = "~4"; break; // Del
+ case 63236: k = "~a"; break; // F1
+ case 63237: k = "~b"; break; // F2
+ case 63238: k = "~c"; break; // F3
+ case 63239: k = "~d"; break; // F4
+ case 63240: k = "~e"; break; // F5
+ case 63241: k = "~f"; break; // F6
+ case 63242: k = "~g"; break; // F7
+ case 63243: k = "~h"; break; // F8
+ case 63244: k = "~i"; break; // F9
+ case 63245: k = "~j"; break; // F10
+ case 63246: k = "~k"; break; // F11
+ case 63247: k = "~l"; break; // F12
+ default: k = String.fromCharCode(kc); break;
+ }
+
+// debug("fromkeydown=" + fromkeydown + ", ev.keyCode=" + ev.keyCode + ", " +
+// "ev.which=" + ev.which + ", ev.ctrlKey=" + ev.ctrlKey + ", " +
+// "kc=" + kc + ", k=" + k);
+
+ queue(encodeURIComponent(k));
+
+ ev.cancelBubble = true;
+ if (ev.stopPropagation) ev.stopPropagation();
+ if (ev.preventDefault) ev.preventDefault();
+
+ return true;
+ }
+
+ function keydown(ev) {
+ if (!ev)
+ ev = window.event;
+ o = { 9:1, 8:1, 27:1, 33:1, 34:1, 35:1, 36:1, 37:1, 38:1, 39:1, 40:1, 45:1, 46:1, 112:1,
+ 113:1, 114:1, 115:1, 116:1, 117:1, 118:1, 119:1, 120:1, 121:1, 122:1, 123:1 };
+ if (o[ev.keyCode] || ev.ctrlKey || ev.altKey) {
+ keypress(ev, true);
+ }
+ }
+
+ function init() {
+ if (typeof(XMLHttpRequest) == "undefined") {
+ XMLHttpRequest = function() {
+ try { return new ActiveXObject("Msxml2.XMLHTTP.6.0"); }
+ catch(e) {}
+ try { return new ActiveXObject("Msxml2.XMLHTTP.3.0"); }
+ catch(e) {}
+ try { return new ActiveXObject("Msxml2.XMLHTTP"); }
+ catch(e) {}
+ try { return new ActiveXObject("Microsoft.XMLHTTP"); }
+ catch(e) {}
+ throw new Error("This browser does not support XMLHttpRequest.");
+ };
+ }
+ sled.appendChild(document.createTextNode('\xb7'));
+ sled.className = 'off';
+ dstat.appendChild(sled);
+ dstat.appendChild(document.createTextNode(' '));
+ dstat.appendChild(sdebug);
+ dstat.className = 'stat';
+ div.appendChild(dstat);
+ var d = document.createElement('div');
+ d.appendChild(dterm);
+ div.appendChild(d);
+ document.onkeypress = keypress;
+ document.onkeydown = keydown;
+ timeout = window.setTimeout(update, 100);
+ }
+
+ init();
+
+}
+
+gogo.Terminal = function(div, width, height) {
+ return new this.Terminal_ctor(div, width, height);
+}
+