diff --git a/console-proxy/.classpath b/console-proxy/.classpath
index 1a61b023647..eeed44e009b 100644
--- a/console-proxy/.classpath
+++ b/console-proxy/.classpath
@@ -1,25 +1,25 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
diff --git a/console-proxy/.project b/console-proxy/.project
index d3efcb5b448..5fae244dad4 100644
--- a/console-proxy/.project
+++ b/console-proxy/.project
@@ -1,41 +1,41 @@
-
-
-
- console-proxy
-
-
-
-
-
- org.eclipse.wst.jsdt.core.javascriptValidator
-
-
-
-
- org.eclipse.jdt.core.javabuilder
-
-
-
-
-
- org.eclipse.jdt.core.javanature
- org.eclipse.wst.jsdt.core.jsNature
-
-
+
+
+
+ console-proxy
+
+
+
+
+
+ org.eclipse.wst.jsdt.core.javascriptValidator
+
+
+
+
+ org.eclipse.jdt.core.javabuilder
+
+
+
+
+
+ org.eclipse.jdt.core.javanature
+ org.eclipse.wst.jsdt.core.jsNature
+
+
diff --git a/console-proxy/conf.dom0/agent.properties.in b/console-proxy/conf.dom0/agent.properties.in
index 285587a44cb..1920481c03f 100644
--- a/console-proxy/conf.dom0/agent.properties.in
+++ b/console-proxy/conf.dom0/agent.properties.in
@@ -1,46 +1,46 @@
-# 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.
-
-# Sample configuration file for VMOPS console proxy
-
-instance=ConsoleProxy
-consoleproxy.httpListenPort=8002
-
-#resource= the java class, which agent load to execute
-resource=com.cloud.agent.resource.consoleproxy.ConsoleProxyResource
-
-#host= The IP address of management server
-host=localhost
-
-#port = The port management server listening on, default is 8250
-port=8250
-
-#pod= The pod, which agent belonged to
-pod=default
-
-#zone= The zone, which agent belonged to
-zone=default
-
-#private.network.device= the private nic device
-# if this is commented, it is autodetected on service startup
-# private.network.device=cloudbr0
-
-#public.network.device= the public nic device
-# if this is commented, it is autodetected on service startup
-# public.network.device=cloudbr0
-
-#guid= a GUID to identify the agent
+# 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.
+
+# Sample configuration file for VMOPS console proxy
+
+instance=ConsoleProxy
+consoleproxy.httpListenPort=8002
+
+#resource= the java class, which agent load to execute
+resource=com.cloud.agent.resource.consoleproxy.ConsoleProxyResource
+
+#host= The IP address of management server
+host=localhost
+
+#port = The port management server listening on, default is 8250
+port=8250
+
+#pod= The pod, which agent belonged to
+pod=default
+
+#zone= The zone, which agent belonged to
+zone=default
+
+#private.network.device= the private nic device
+# if this is commented, it is autodetected on service startup
+# private.network.device=cloudbr0
+
+#public.network.device= the public nic device
+# if this is commented, it is autodetected on service startup
+# public.network.device=cloudbr0
+
+#guid= a GUID to identify the agent
diff --git a/console-proxy/conf.dom0/consoleproxy.properties.in b/console-proxy/conf.dom0/consoleproxy.properties.in
index 858ef444cd3..a3cddbcab96 100644
--- a/console-proxy/conf.dom0/consoleproxy.properties.in
+++ b/console-proxy/conf.dom0/consoleproxy.properties.in
@@ -1,23 +1,23 @@
-# 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.
-
-consoleproxy.tcpListenPort=0
-consoleproxy.httpListenPort=80
-consoleproxy.httpCmdListenPort=8001
-consoleproxy.jarDir=./applet/
-consoleproxy.viewerLinger=180
-consoleproxy.reconnectMaxRetry=5
+# 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.
+
+consoleproxy.tcpListenPort=0
+consoleproxy.httpListenPort=80
+consoleproxy.httpCmdListenPort=8001
+consoleproxy.jarDir=./applet/
+consoleproxy.viewerLinger=180
+consoleproxy.reconnectMaxRetry=5
diff --git a/console-proxy/conf/agent.properties b/console-proxy/conf/agent.properties
index 11853ba6ca9..4e217f21100 100644
--- a/console-proxy/conf/agent.properties
+++ b/console-proxy/conf/agent.properties
@@ -1,19 +1,19 @@
-# 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.
-
-instance=ConsoleProxy
-resource=com.cloud.agent.resource.consoleproxy.ConsoleProxyResource
+# 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.
+
+instance=ConsoleProxy
+resource=com.cloud.agent.resource.consoleproxy.ConsoleProxyResource
diff --git a/console-proxy/conf/consoleproxy.properties b/console-proxy/conf/consoleproxy.properties
index 3e5f69ab241..bb452f5823c 100644
--- a/console-proxy/conf/consoleproxy.properties
+++ b/console-proxy/conf/consoleproxy.properties
@@ -1,23 +1,23 @@
-# 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.
-
-consoleproxy.tcpListenPort=0
-consoleproxy.httpListenPort=8088
-consoleproxy.httpCmdListenPort=8001
-consoleproxy.jarDir=./applet/
-consoleproxy.viewerLinger=180
-consoleproxy.reconnectMaxRetry=5
+# 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.
+
+consoleproxy.tcpListenPort=0
+consoleproxy.httpListenPort=8088
+consoleproxy.httpCmdListenPort=8001
+consoleproxy.jarDir=./applet/
+consoleproxy.viewerLinger=180
+consoleproxy.reconnectMaxRetry=5
diff --git a/console-proxy/css/ajaxviewer.css b/console-proxy/css/ajaxviewer.css
index 90c1a63bb29..5ea552b176f 100644
--- a/console-proxy/css/ajaxviewer.css
+++ b/console-proxy/css/ajaxviewer.css
@@ -1,144 +1,144 @@
-/*
-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.
-*/
-
-body {
- margin:0 0;
- text-align: center;
-}
-
-#main_panel {
- clear:both;
- margin: 0 auto;
- text-align: left;
-}
-
-.canvas_tile {
- cursor:crosshair;
-}
-
-#toolbar {
- font:normal 12px 'Trebuchet MS','Arial';
- margin:0 auto;
- text-align: left;
- padding:0 0;
- height:32px;
- background-image:url(/resource/images/back.gif);
- background-repeat:repeat-x;
-}
-
-#toolbar ul {
- margin:0 0;
- padding:0 10px 0 10px;
- float:left;
- display:block;
- line-height:32px;
- list-style:none;
-}
-
-#toolbar li {
- float:left;
- display:inline;
- padding:0;
- height:32px;
-}
-
-#toolbar a {
- color:white;
- float:left;
- display:block;
- padding:0 3px 0 3px;
- text-decoration:none;
- line-height:32px;
-}
-
-#toolbar a span {
- display:block;
- float:none;
- padding:0 10px 0 7px;
-}
-
-#toolbar a span img {
- border:none;
- margin:8px 4px 0 0;
-}
-
-#toolbar a:hover {
- background: url(/resource/images/left.png) no-repeat left center;
-}
-
-#toolbar a:hover span {
- background:url(/resource/images/right.png) no-repeat right center;
-}
-
-
-#toolbar ul li ul {
- position: absolute;
- top:32;
- width: 260;
- height: 65;
- display: block;
- display: none;
- border-top: 1px solid black;
- background-image:url(/resource/images/back.gif);
- background-repeat:repeat-x repeat-y;
-}
-
-#toolbar ul li ul li {
- display: list-item;
- float:none;
- padding-left: 20;
-}
-
-#toolbar ul li ul li.current {
- background: url(/resource/images/cad.gif) no-repeat left center;
-}
-
-#toolbar ul li ul li a {
- display:block;
- padding:0 3px 0 3px;
- text-decoration:none;
- line-height:32px;
- vertical-align: bottom; /* this is to fix the list gap in IE */
-}
-
-#toolbar ul li ul li a:hover {
- background: url(/resource/images/left.png) no-repeat left center;
-}
-
-#toolbar ul li ul li a:hover span {
- background: url(/resource/images/right2.png) no-repeat right center;
-}
-
-span.dark {
- margin-right:20px;
- float:right;
- display:block;
- width:32px;
- height:30px;
- background:url(/resource/images/gray-green.png) no-repeat center center;
-}
-
-span.bright {
- margin-right:20px;
- float:right;
- display:block;
- width:32px;
- height:30px;
- background:url(/resource/images/bright-green.png) no-repeat center center;
-}
+/*
+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.
+*/
+
+body {
+ margin:0 0;
+ text-align: center;
+}
+
+#main_panel {
+ clear:both;
+ margin: 0 auto;
+ text-align: left;
+}
+
+.canvas_tile {
+ cursor:crosshair;
+}
+
+#toolbar {
+ font:normal 12px 'Trebuchet MS','Arial';
+ margin:0 auto;
+ text-align: left;
+ padding:0 0;
+ height:32px;
+ background-image:url(/resource/images/back.gif);
+ background-repeat:repeat-x;
+}
+
+#toolbar ul {
+ margin:0 0;
+ padding:0 10px 0 10px;
+ float:left;
+ display:block;
+ line-height:32px;
+ list-style:none;
+}
+
+#toolbar li {
+ float:left;
+ display:inline;
+ padding:0;
+ height:32px;
+}
+
+#toolbar a {
+ color:white;
+ float:left;
+ display:block;
+ padding:0 3px 0 3px;
+ text-decoration:none;
+ line-height:32px;
+}
+
+#toolbar a span {
+ display:block;
+ float:none;
+ padding:0 10px 0 7px;
+}
+
+#toolbar a span img {
+ border:none;
+ margin:8px 4px 0 0;
+}
+
+#toolbar a:hover {
+ background: url(/resource/images/left.png) no-repeat left center;
+}
+
+#toolbar a:hover span {
+ background:url(/resource/images/right.png) no-repeat right center;
+}
+
+
+#toolbar ul li ul {
+ position: absolute;
+ top:32;
+ width: 260;
+ height: 65;
+ display: block;
+ display: none;
+ border-top: 1px solid black;
+ background-image:url(/resource/images/back.gif);
+ background-repeat:repeat-x repeat-y;
+}
+
+#toolbar ul li ul li {
+ display: list-item;
+ float:none;
+ padding-left: 20;
+}
+
+#toolbar ul li ul li.current {
+ background: url(/resource/images/cad.gif) no-repeat left center;
+}
+
+#toolbar ul li ul li a {
+ display:block;
+ padding:0 3px 0 3px;
+ text-decoration:none;
+ line-height:32px;
+ vertical-align: bottom; /* this is to fix the list gap in IE */
+}
+
+#toolbar ul li ul li a:hover {
+ background: url(/resource/images/left.png) no-repeat left center;
+}
+
+#toolbar ul li ul li a:hover span {
+ background: url(/resource/images/right2.png) no-repeat right center;
+}
+
+span.dark {
+ margin-right:20px;
+ float:right;
+ display:block;
+ width:32px;
+ height:30px;
+ background:url(/resource/images/gray-green.png) no-repeat center center;
+}
+
+span.bright {
+ margin-right:20px;
+ float:right;
+ display:block;
+ width:32px;
+ height:30px;
+ background:url(/resource/images/bright-green.png) no-repeat center center;
+}
diff --git a/console-proxy/js/ajaxviewer.js b/console-proxy/js/ajaxviewer.js
index b15642a1da1..355cc827ba2 100644
--- a/console-proxy/js/ajaxviewer.js
+++ b/console-proxy/js/ajaxviewer.js
@@ -22,27 +22,27 @@ var g_logger;
/////////////////////////////////////////////////////////////////////////////
// class StringBuilder
//
-function StringBuilder(initStr) {
- this.strings = new Array("");
- this.append(initStr);
-}
-
-StringBuilder.prototype = {
- append : function (str) {
- if (str) {
- this.strings.push(str);
- }
- return this;
- },
-
- clear : function() {
- this.strings.length = 1;
- return this;
- },
-
- toString: function() {
- return this.strings.join("");
- }
+function StringBuilder(initStr) {
+ this.strings = new Array("");
+ this.append(initStr);
+}
+
+StringBuilder.prototype = {
+ append : function (str) {
+ if (str) {
+ this.strings.push(str);
+ }
+ return this;
+ },
+
+ clear : function() {
+ this.strings.length = 1;
+ return this;
+ },
+
+ toString: function() {
+ return this.strings.join("");
+ }
};
@@ -335,36 +335,36 @@ function AjaxViewer(panelId, imageUrl, updateUrl, tileMap, width, height, tileWi
// g_logger.enable(true);
// g_logger.open();
- var ajaxViewer = this;
- this.imageLoaded = false;
- this.fullImage = true;
- this.imgUrl = imageUrl;
- this.img = new Image();
- $(this.img).attr('src', imageUrl).load(function() {
- ajaxViewer.imageLoaded = true;
- });
-
- this.updateUrl = updateUrl;
- this.tileMap = tileMap;
- this.dirty = true;
- this.width = width;
- this.height = height;
- this.tileWidth = tileWidth;
+ var ajaxViewer = this;
+ this.imageLoaded = false;
+ this.fullImage = true;
+ this.imgUrl = imageUrl;
+ this.img = new Image();
+ $(this.img).attr('src', imageUrl).load(function() {
+ ajaxViewer.imageLoaded = true;
+ });
+
+ this.updateUrl = updateUrl;
+ this.tileMap = tileMap;
+ this.dirty = true;
+ this.width = width;
+ this.height = height;
+ this.tileWidth = tileWidth;
this.tileHeight = tileHeight;
this.maxTileZIndex = 1;
this.currentKeyboard = AjaxViewer.KEYBOARD_TYPE_ENGLISH;
this.keyboardMappers = [];
- this.timer = 0;
- this.eventQueue = [];
- this.sendingEventInProgress = false;
-
- this.lastClickEvent = { x: 0, y: 0, button: 0, modifiers: 0, time: new Date().getTime() };
-
- if(window.onStatusNotify == undefined)
- window.onStatusNotify = function(status) {};
-
+ this.timer = 0;
+ this.eventQueue = [];
+ this.sendingEventInProgress = false;
+
+ this.lastClickEvent = { x: 0, y: 0, button: 0, modifiers: 0, time: new Date().getTime() };
+
+ if(window.onStatusNotify == undefined)
+ window.onStatusNotify = function(status) {};
+
this.panel = this.generateCanvas(panelId, width, height, tileWidth, tileHeight);
this.setupKeyboardTranslationTable();
@@ -569,86 +569,86 @@ AjaxViewer.getEventName = function(type) {
return "N/A";
};
-
-AjaxViewer.prototype = {
- setDirty: function(value) {
- this.dirty = value;
- },
-
- isDirty: function() {
- return this.dirty;
- },
-
- isImageLoaded: function() {
- return this.imageLoaded;
- },
-
- refresh: function(imageUrl, tileMap, fullImage) {
- var ajaxViewer = this;
- var img = $(this.img);
- this.fullImage = fullImage;
- this.imgUrl=imageUrl;
-
- img.attr('src', imageUrl).load(function() {
- ajaxViewer.imageLoaded = true;
- });
- this.tileMap = tileMap;
- },
-
- resize: function(panelId, width, height, tileWidth, tileHeight) {
- $(".canvas_tile", document.body).each(function() {
- $(this).remove();
- });
- $("table", $("#" + panelId)).remove();
-
- this.width = width;
- this.height = height;
- this.tileWidth = tileWidth;
- this.tileHeight = tileHeight;
- this.panel = this.generateCanvas(panelId, width, height, tileWidth, tileHeight);
- },
-
- start: function() {
- var ajaxViewer = this;
- this.timer = setInterval(function() { ajaxViewer.heartbeat(); }, 50);
-
- $(document).bind("ajaxError", function(event, XMLHttpRequest, ajaxOptions, thrownError) {
- ajaxViewer.onAjaxError(event, XMLHttpRequest, ajaxOptions, thrownError);
- });
-
- this.eventQueue = []; // reset event queue
- this.sendingEventInProgress = false;
- ajaxViewer.installMouseHook();
- ajaxViewer.installKeyboardHook();
-
- $(window).bind("resize", function() {
- ajaxViewer.onWindowResize();
- });
- },
-
- stop: function() {
- clearInterval(this.timer);
- this.deleteCanvas();
-
- this.uninstallMouseHook();
- this.uninstallKeyboardHook();
- this.eventQueue = [];
- this.sendingEventInProgress = false;
-
- $(document).unbind("ajaxError");
- $(window).unbind("resize");
- },
-
- sendMouseEvent: function(event, x, y, whichButton, modifiers) {
- this.eventQueue.push({
- type: AjaxViewer.EVENT_QUEUE_MOUSE_EVENT,
- event: event,
- x: x,
- y: y,
- code: whichButton,
- modifiers: modifiers
- });
- this.checkEventQueue();
+
+AjaxViewer.prototype = {
+ setDirty: function(value) {
+ this.dirty = value;
+ },
+
+ isDirty: function() {
+ return this.dirty;
+ },
+
+ isImageLoaded: function() {
+ return this.imageLoaded;
+ },
+
+ refresh: function(imageUrl, tileMap, fullImage) {
+ var ajaxViewer = this;
+ var img = $(this.img);
+ this.fullImage = fullImage;
+ this.imgUrl=imageUrl;
+
+ img.attr('src', imageUrl).load(function() {
+ ajaxViewer.imageLoaded = true;
+ });
+ this.tileMap = tileMap;
+ },
+
+ resize: function(panelId, width, height, tileWidth, tileHeight) {
+ $(".canvas_tile", document.body).each(function() {
+ $(this).remove();
+ });
+ $("table", $("#" + panelId)).remove();
+
+ this.width = width;
+ this.height = height;
+ this.tileWidth = tileWidth;
+ this.tileHeight = tileHeight;
+ this.panel = this.generateCanvas(panelId, width, height, tileWidth, tileHeight);
+ },
+
+ start: function() {
+ var ajaxViewer = this;
+ this.timer = setInterval(function() { ajaxViewer.heartbeat(); }, 50);
+
+ $(document).bind("ajaxError", function(event, XMLHttpRequest, ajaxOptions, thrownError) {
+ ajaxViewer.onAjaxError(event, XMLHttpRequest, ajaxOptions, thrownError);
+ });
+
+ this.eventQueue = []; // reset event queue
+ this.sendingEventInProgress = false;
+ ajaxViewer.installMouseHook();
+ ajaxViewer.installKeyboardHook();
+
+ $(window).bind("resize", function() {
+ ajaxViewer.onWindowResize();
+ });
+ },
+
+ stop: function() {
+ clearInterval(this.timer);
+ this.deleteCanvas();
+
+ this.uninstallMouseHook();
+ this.uninstallKeyboardHook();
+ this.eventQueue = [];
+ this.sendingEventInProgress = false;
+
+ $(document).unbind("ajaxError");
+ $(window).unbind("resize");
+ },
+
+ sendMouseEvent: function(event, x, y, whichButton, modifiers) {
+ this.eventQueue.push({
+ type: AjaxViewer.EVENT_QUEUE_MOUSE_EVENT,
+ event: event,
+ x: x,
+ y: y,
+ code: whichButton,
+ modifiers: modifiers
+ });
+ this.checkEventQueue();
},
setupKeyboardTranslationTable : function() {
@@ -799,487 +799,487 @@ AjaxViewer.prototype = {
}
}
- var len;
+ var len;
g_logger.log(Logger.LEVEL_INFO, "Keyboard event: " + AjaxViewer.getEventName(event) + ", code: " + code + ", modifiers: " + modifiers + ', char: ' + String.fromCharCode(code));
- this.eventQueue.push({
- type: AjaxViewer.EVENT_QUEUE_KEYBOARD_EVENT,
- event: event,
- code: code,
- modifiers: modifiers
+ this.eventQueue.push({
+ type: AjaxViewer.EVENT_QUEUE_KEYBOARD_EVENT,
+ event: event,
+ code: code,
+ modifiers: modifiers
});
- if(event != AjaxViewer.KEY_DOWN)
- this.checkEventQueue();
- },
-
- aggregateEvents: function() {
- var ajaxViewer = this;
- var aggratedQueue = [];
-
- var aggregating = false;
- var mouseX;
- var mouseY;
- $.each(ajaxViewer.eventQueue, function(index, item) {
- if(item.type != AjaxViewer.EVENT_QUEUE_MOUSE_EVENT) {
- aggratedQueue.push(item);
- } else {
- if(!aggregating) {
- if(item.event == AjaxViewer.MOUSE_MOVE) {
- aggregating = true;
- mouseX = item.x;
- mouseY = item.y;
- } else {
- aggratedQueue.push(item);
- }
- } else {
- if(item.event == AjaxViewer.MOUSE_MOVE) {
- // continue to aggregate mouse move event
- mouseX = item.x;
- mouseY = item.y;
- } else {
- aggratedQueue.push({
- type: AjaxViewer.EVENT_QUEUE_MOUSE_EVENT,
- event: AjaxViewer.MOUSE_MOVE,
- x: mouseX,
- y: mouseY,
- code: 0,
- modifiers: 0
- });
- aggregating = false;
-
- aggratedQueue.push(item);
- }
- }
- }
- });
-
- if(aggregating) {
- aggratedQueue.push({
- type: AjaxViewer.EVENT_QUEUE_MOUSE_EVENT,
- event: AjaxViewer.MOUSE_MOVE,
- x: mouseX,
- y: mouseY,
- code: 0,
- modifiers: 0
- });
- }
-
- this.eventQueue = aggratedQueue;
- },
-
- checkEventQueue: function() {
+ if(event != AjaxViewer.KEY_DOWN)
+ this.checkEventQueue();
+ },
+
+ aggregateEvents: function() {
var ajaxViewer = this;
-
+ var aggratedQueue = [];
+
+ var aggregating = false;
+ var mouseX;
+ var mouseY;
+ $.each(ajaxViewer.eventQueue, function(index, item) {
+ if(item.type != AjaxViewer.EVENT_QUEUE_MOUSE_EVENT) {
+ aggratedQueue.push(item);
+ } else {
+ if(!aggregating) {
+ if(item.event == AjaxViewer.MOUSE_MOVE) {
+ aggregating = true;
+ mouseX = item.x;
+ mouseY = item.y;
+ } else {
+ aggratedQueue.push(item);
+ }
+ } else {
+ if(item.event == AjaxViewer.MOUSE_MOVE) {
+ // continue to aggregate mouse move event
+ mouseX = item.x;
+ mouseY = item.y;
+ } else {
+ aggratedQueue.push({
+ type: AjaxViewer.EVENT_QUEUE_MOUSE_EVENT,
+ event: AjaxViewer.MOUSE_MOVE,
+ x: mouseX,
+ y: mouseY,
+ code: 0,
+ modifiers: 0
+ });
+ aggregating = false;
+
+ aggratedQueue.push(item);
+ }
+ }
+ }
+ });
+
+ if(aggregating) {
+ aggratedQueue.push({
+ type: AjaxViewer.EVENT_QUEUE_MOUSE_EVENT,
+ event: AjaxViewer.MOUSE_MOVE,
+ x: mouseX,
+ y: mouseY,
+ code: 0,
+ modifiers: 0
+ });
+ }
+
+ this.eventQueue = aggratedQueue;
+ },
+
+ checkEventQueue: function() {
+ var ajaxViewer = this;
+
if(!this.sendingEventInProgress && this.eventQueue.length > 0) {
- var sb = new StringBuilder();
- sb.append(""+this.eventQueue.length).append("|");
- $.each(this.eventQueue, function() {
- var item = this;
- if(item.type == AjaxViewer.EVENT_QUEUE_MOUSE_EVENT) {
- sb.append(""+item.type).append("|");
- sb.append(""+item.event).append("|");
- sb.append(""+item.x).append("|");
- sb.append(""+item.y).append("|");
- sb.append(""+item.code).append("|");
- sb.append(""+item.modifiers).append("|");
- } else {
- sb.append(""+item.type).append("|");
- sb.append(""+item.event).append("|");
- sb.append(""+item.code).append("|");
- sb.append(""+item.modifiers).append("|");
- }
- });
- this.eventQueue.length = 0;
-
+ var sb = new StringBuilder();
+ sb.append(""+this.eventQueue.length).append("|");
+ $.each(this.eventQueue, function() {
+ var item = this;
+ if(item.type == AjaxViewer.EVENT_QUEUE_MOUSE_EVENT) {
+ sb.append(""+item.type).append("|");
+ sb.append(""+item.event).append("|");
+ sb.append(""+item.x).append("|");
+ sb.append(""+item.y).append("|");
+ sb.append(""+item.code).append("|");
+ sb.append(""+item.modifiers).append("|");
+ } else {
+ sb.append(""+item.type).append("|");
+ sb.append(""+item.event).append("|");
+ sb.append(""+item.code).append("|");
+ sb.append(""+item.modifiers).append("|");
+ }
+ });
+ this.eventQueue.length = 0;
+
var url = ajaxViewer.updateUrl + "&event=" + AjaxViewer.EVENT_BAG;
g_logger.log(Logger.LEVEL_TRACE, "Posting client event " + sb.toString() + "...");
-
- ajaxViewer.sendingEventInProgress = true;
- window.onStatusNotify(AjaxViewer.STATUS_SENDING);
+
+ ajaxViewer.sendingEventInProgress = true;
+ window.onStatusNotify(AjaxViewer.STATUS_SENDING);
$.post(url, {data: sb.toString()}, function(data, textStatus) {
g_logger.log(Logger.LEVEL_TRACE, "Client event " + sb.toString() + " is posted");
-
- ajaxViewer.sendingEventInProgress = false;
- window.onStatusNotify(AjaxViewer.STATUS_SENT);
-
- ajaxViewer.checkUpdate();
- }, 'html');
- }
- },
-
- onAjaxError: function(event, XMLHttpRequest, ajaxOptions, thrownError) {
- if(window.onClientError != undefined && jQuery.isFunction(window.onClientError)) {
- window.onClientError();
- }
- },
-
- onWindowResize: function() {
- var offset = this.panel.offset();
-
- var row = $('tr:first', this.panel);
- var cell = $('td:first', row);
- var tile = this.getTile(cell, 'tile');
-
- var tileOffset = tile.offset();
- var deltaX = offset.left - tileOffset.left;
- var deltaY = offset.top - tileOffset.top;
-
- if(deltaX != 0 || deltaY != 0) {
- $(".canvas_tile").each(function() {
- var offsetFrom = $(this).offset();
- $(this).css('left', offsetFrom.left + deltaX).css('top', offsetFrom.top + deltaY);
- });
- }
- },
-
- deleteCanvas: function() {
- $('.canvas_tile', $(document.body)).each(function() {
- $(this).remove();
- });
- },
-
- generateCanvas: function(wrapperDivId, width, height, tileWidth, tileHeight) {
- var canvasParent = $('#' + wrapperDivId);
- canvasParent.width(width);
- canvasParent.height(height);
-
- if(window.onCanvasSizeChange != undefined && jQuery.isFunction(window.onCanvasSizeChange))
- window.onCanvasSizeChange(width, height);
-
- var tableDef = '
\r\n';
- var i = 0;
- var j = 0;
- for(i = 0; i < Math.ceil((height + tileHeight - 1) / tileHeight); i++) {
- var rowHeight = Math.min(height - i*tileHeight, tileHeight);
- tableDef += '\r\n';
-
- for(j = 0; j < Math.ceil((width + tileWidth - 1) / tileWidth); j++) {
- var colWidth = Math.min(width - j*tileWidth, tileWidth);
- tableDef += ' | \r\n';
- }
- tableDef += '
\r\n';
- }
- tableDef += '
\r\n';
-
- return $(tableDef).appendTo(canvasParent);
- },
-
- getTile: function(cell, name) {
- var clonedDiv = cell.data(name);
- if(!clonedDiv) {
- var offset = cell.offset();
- var divDef = "";
-
- clonedDiv = $(divDef).appendTo($(document.body));
- cell.data(name, clonedDiv);
- }
-
- return clonedDiv;
- },
-
- initCell: function(cell) {
- if(!cell.data("init")) {
- cell.data("init", true);
-
- cell.data("current", 0);
- this.getTile(cell, "tile2");
- this.getTile(cell, "tile");
- }
- },
-
- displayCell: function(cell, bg) {
- var div;
- var divPrev;
- if(!cell.data("current")) {
- cell.data("current", 1);
-
- divPrev = this.getTile(cell, "tile");
- div = this.getTile(cell, "tile2");
- } else {
- cell.data("current", 0);
- divPrev = this.getTile(cell, "tile2");
- div = this.getTile(cell, "tile");
- }
+
+ ajaxViewer.sendingEventInProgress = false;
+ window.onStatusNotify(AjaxViewer.STATUS_SENT);
+
+ ajaxViewer.checkUpdate();
+ }, 'html');
+ }
+ },
+
+ onAjaxError: function(event, XMLHttpRequest, ajaxOptions, thrownError) {
+ if(window.onClientError != undefined && jQuery.isFunction(window.onClientError)) {
+ window.onClientError();
+ }
+ },
+
+ onWindowResize: function() {
+ var offset = this.panel.offset();
+
+ var row = $('tr:first', this.panel);
+ var cell = $('td:first', row);
+ var tile = this.getTile(cell, 'tile');
+
+ var tileOffset = tile.offset();
+ var deltaX = offset.left - tileOffset.left;
+ var deltaY = offset.top - tileOffset.top;
+
+ if(deltaX != 0 || deltaY != 0) {
+ $(".canvas_tile").each(function() {
+ var offsetFrom = $(this).offset();
+ $(this).css('left', offsetFrom.left + deltaX).css('top', offsetFrom.top + deltaY);
+ });
+ }
+ },
+
+ deleteCanvas: function() {
+ $('.canvas_tile', $(document.body)).each(function() {
+ $(this).remove();
+ });
+ },
+
+ generateCanvas: function(wrapperDivId, width, height, tileWidth, tileHeight) {
+ var canvasParent = $('#' + wrapperDivId);
+ canvasParent.width(width);
+ canvasParent.height(height);
+
+ if(window.onCanvasSizeChange != undefined && jQuery.isFunction(window.onCanvasSizeChange))
+ window.onCanvasSizeChange(width, height);
+
+ var tableDef = '\r\n';
+ var i = 0;
+ var j = 0;
+ for(i = 0; i < Math.ceil((height + tileHeight - 1) / tileHeight); i++) {
+ var rowHeight = Math.min(height - i*tileHeight, tileHeight);
+ tableDef += '\r\n';
+
+ for(j = 0; j < Math.ceil((width + tileWidth - 1) / tileWidth); j++) {
+ var colWidth = Math.min(width - j*tileWidth, tileWidth);
+ tableDef += ' | \r\n';
+ }
+ tableDef += '
\r\n';
+ }
+ tableDef += '
\r\n';
+
+ return $(tableDef).appendTo(canvasParent);
+ },
+
+ getTile: function(cell, name) {
+ var clonedDiv = cell.data(name);
+ if(!clonedDiv) {
+ var offset = cell.offset();
+ var divDef = "";
+
+ clonedDiv = $(divDef).appendTo($(document.body));
+ cell.data(name, clonedDiv);
+ }
+
+ return clonedDiv;
+ },
+
+ initCell: function(cell) {
+ if(!cell.data("init")) {
+ cell.data("init", true);
+
+ cell.data("current", 0);
+ this.getTile(cell, "tile2");
+ this.getTile(cell, "tile");
+ }
+ },
+
+ displayCell: function(cell, bg) {
+ var div;
+ var divPrev;
+ if(!cell.data("current")) {
+ cell.data("current", 1);
+
+ divPrev = this.getTile(cell, "tile");
+ div = this.getTile(cell, "tile2");
+ } else {
+ cell.data("current", 0);
+ divPrev = this.getTile(cell, "tile2");
+ div = this.getTile(cell, "tile");
+ }
var zIndex = parseInt(divPrev.css("z-index")) + 1;
- this.maxTileZIndex = Math.max(this.maxTileZIndex, zIndex);
- div.css("z-index", zIndex);
- div.css("background", bg);
- },
-
- updateTile: function() {
- if(this.dirty) {
- var ajaxViewer = this;
- var tileWidth = this.tileWidth;
- var tileHeight = this.tileHeight;
- var imgUrl = this.imgUrl;
- var panel = this.panel;
-
- if(this.fullImage) {
- $.each(this.tileMap, function() {
- var i = $(this)[0];
- var j = $(this)[1];
- var row = $("TR:eq("+i+")", panel);
- var cell = $("TD:eq("+j+")", row);
- var attr = "url(" + imgUrl + ") -"+j*tileWidth+"px -"+i*tileHeight + "px";
-
- ajaxViewer.initCell(cell);
- ajaxViewer.displayCell(cell, attr);
- });
- } else {
- $.each(this.tileMap, function(index) {
- var i = $(this)[0];
- var j = $(this)[1];
- var offset = index*tileWidth;
- var attr = "url(" + imgUrl + ") no-repeat -"+offset+"px 0px";
- var row = $("TR:eq("+i+")", panel);
- var cell = $("TD:eq("+j+")", row);
-
- ajaxViewer.initCell(cell);
- ajaxViewer.displayCell(cell, attr);
- });
- }
-
- this.dirty = false;
- }
- },
-
- heartbeat: function() {
- this.checkEventQueue();
- this.checkUpdate();
- },
-
- checkUpdate: function() {
- if(!this.isDirty())
- return;
-
- if(this.isImageLoaded()) {
- this.updateTile();
- var url = this.updateUrl;
- var ajaxViewer = this;
-
- window.onStatusNotify(AjaxViewer.STATUS_RECEIVING);
- $.getScript(url, function(data, textStatus) {
- if(/^/.test(data)) {
- ajaxViewer.stop();
- $(document.body).html(data);
- } else {
- eval(data);
- ajaxViewer.setDirty(true);
- window.onStatusNotify(AjaxViewer.STATUS_RECEIVED);
-
- ajaxViewer.checkUpdate();
- }
- });
- }
- },
-
- ptInPanel: function(pageX, pageY) {
- var mainPanel = this.panel;
-
- var offset = mainPanel.offset();
- var x = pageX - offset.left;
- var y = pageY - offset.top;
-
- if(x < 0 || y < 0 || x > mainPanel.width() - 1 || y > mainPanel.height() - 1)
- return false;
- return true;
- },
-
- pageToPanel: function(pageX, pageY) {
- var mainPanel = this.panel;
-
- var offset = mainPanel.offset();
- var x = pageX - offset.left;
- var y = pageY - offset.top;
-
- if(x < 0)
- x = 0;
- if(x > mainPanel.width() - 1)
- x = mainPanel.width() - 1;
-
- if(y < 0)
- y = 0;
- if(y > mainPanel.height() - 1)
- y = mainPanel.height() - 1;
-
- return { x: Math.ceil(x), y: Math.ceil(y) };
- },
-
- installMouseHook: function() {
- var ajaxViewer = this;
- var target = $(document.body);
-
- target.mousemove(function(e) {
- if(!ajaxViewer.ptInPanel(e.pageX, e.pageY))
- return true;
-
- var pt = ajaxViewer.pageToPanel(e.pageX, e.pageY);
- ajaxViewer.onMouseMove(pt.x, pt.y);
-
- e.stopPropagation();
- return false;
- });
-
- target.mousedown(function(e) {
- ajaxViewer.panel.parent().focus();
-
- if(!ajaxViewer.ptInPanel(e.pageX, e.pageY))
- return true;
+ this.maxTileZIndex = Math.max(this.maxTileZIndex, zIndex);
+ div.css("z-index", zIndex);
+ div.css("background", bg);
+ },
+
+ updateTile: function() {
+ if(this.dirty) {
+ var ajaxViewer = this;
+ var tileWidth = this.tileWidth;
+ var tileHeight = this.tileHeight;
+ var imgUrl = this.imgUrl;
+ var panel = this.panel;
- var modifiers = ajaxViewer.getKeyModifiers(e);
- var whichButton = e.button;
-
- var pt = ajaxViewer.pageToPanel(e.pageX, e.pageY);
- ajaxViewer.onMouseDown(pt.x, pt.y, whichButton, modifiers);
-
- e.stopPropagation();
- return false;
- });
-
- target.mouseup(function(e) {
- if(!ajaxViewer.ptInPanel(e.pageX, e.pageY))
- return true;
-
- var modifiers = ajaxViewer.getKeyModifiers(e);
- var whichButton = e.button;
-
- var pt = ajaxViewer.pageToPanel(e.pageX, e.pageY);
+ if(this.fullImage) {
+ $.each(this.tileMap, function() {
+ var i = $(this)[0];
+ var j = $(this)[1];
+ var row = $("TR:eq("+i+")", panel);
+ var cell = $("TD:eq("+j+")", row);
+ var attr = "url(" + imgUrl + ") -"+j*tileWidth+"px -"+i*tileHeight + "px";
+
+ ajaxViewer.initCell(cell);
+ ajaxViewer.displayCell(cell, attr);
+ });
+ } else {
+ $.each(this.tileMap, function(index) {
+ var i = $(this)[0];
+ var j = $(this)[1];
+ var offset = index*tileWidth;
+ var attr = "url(" + imgUrl + ") no-repeat -"+offset+"px 0px";
+ var row = $("TR:eq("+i+")", panel);
+ var cell = $("TD:eq("+j+")", row);
+
+ ajaxViewer.initCell(cell);
+ ajaxViewer.displayCell(cell, attr);
+ });
+ }
+
+ this.dirty = false;
+ }
+ },
+
+ heartbeat: function() {
+ this.checkEventQueue();
+ this.checkUpdate();
+ },
+
+ checkUpdate: function() {
+ if(!this.isDirty())
+ return;
+
+ if(this.isImageLoaded()) {
+ this.updateTile();
+ var url = this.updateUrl;
+ var ajaxViewer = this;
+
+ window.onStatusNotify(AjaxViewer.STATUS_RECEIVING);
+ $.getScript(url, function(data, textStatus) {
+ if(/^/.test(data)) {
+ ajaxViewer.stop();
+ $(document.body).html(data);
+ } else {
+ eval(data);
+ ajaxViewer.setDirty(true);
+ window.onStatusNotify(AjaxViewer.STATUS_RECEIVED);
+
+ ajaxViewer.checkUpdate();
+ }
+ });
+ }
+ },
+
+ ptInPanel: function(pageX, pageY) {
+ var mainPanel = this.panel;
+
+ var offset = mainPanel.offset();
+ var x = pageX - offset.left;
+ var y = pageY - offset.top;
+
+ if(x < 0 || y < 0 || x > mainPanel.width() - 1 || y > mainPanel.height() - 1)
+ return false;
+ return true;
+ },
+
+ pageToPanel: function(pageX, pageY) {
+ var mainPanel = this.panel;
+
+ var offset = mainPanel.offset();
+ var x = pageX - offset.left;
+ var y = pageY - offset.top;
+
+ if(x < 0)
+ x = 0;
+ if(x > mainPanel.width() - 1)
+ x = mainPanel.width() - 1;
+
+ if(y < 0)
+ y = 0;
+ if(y > mainPanel.height() - 1)
+ y = mainPanel.height() - 1;
+
+ return { x: Math.ceil(x), y: Math.ceil(y) };
+ },
+
+ installMouseHook: function() {
+ var ajaxViewer = this;
+ var target = $(document.body);
+
+ target.mousemove(function(e) {
+ if(!ajaxViewer.ptInPanel(e.pageX, e.pageY))
+ return true;
+
+ var pt = ajaxViewer.pageToPanel(e.pageX, e.pageY);
+ ajaxViewer.onMouseMove(pt.x, pt.y);
+
+ e.stopPropagation();
+ return false;
+ });
+
+ target.mousedown(function(e) {
+ ajaxViewer.panel.parent().focus();
+
+ if(!ajaxViewer.ptInPanel(e.pageX, e.pageY))
+ return true;
+
+ var modifiers = ajaxViewer.getKeyModifiers(e);
+ var whichButton = e.button;
+
+ var pt = ajaxViewer.pageToPanel(e.pageX, e.pageY);
+ ajaxViewer.onMouseDown(pt.x, pt.y, whichButton, modifiers);
+
+ e.stopPropagation();
+ return false;
+ });
+
+ target.mouseup(function(e) {
+ if(!ajaxViewer.ptInPanel(e.pageX, e.pageY))
+ return true;
+
+ var modifiers = ajaxViewer.getKeyModifiers(e);
+ var whichButton = e.button;
+
+ var pt = ajaxViewer.pageToPanel(e.pageX, e.pageY);
+
+ ajaxViewer.onMouseUp(pt.x, pt.y, whichButton, modifiers);
+ e.stopPropagation();
+ return false;
+ });
+
+ // disable browser right-click context menu
+ target.bind("contextmenu", function() { return false; });
+ },
+
+ uninstallMouseHook : function() {
+ var target = $(document);
+ target.unbind("mousemove");
+ target.unbind("mousedown");
+ target.unbind("mouseup");
+ target.unbind("contextmenu");
+ },
+
+ requiresDefaultKeyProcess : function(e) {
+ switch(e.which) {
+ case 8 : // backspace
+ case 9 : // TAB
+ case 19 : // PAUSE/BREAK
+ case 20 : // CAPSLOCK
+ case 27 : // ESCAPE
+ case 16 : // SHIFT key
+ case 17 : // CTRL key
+ case 18 : // ALT key
+ case 33 : // PGUP
+ case 34 : // PGDN
+ case 35 : // END
+ case 36 : // HOME
+ case 37 : // LEFT
+ case 38 : // UP
+ case 39 : // RIGHT
+ case 40 : // DOWN
+ return false;
+ }
+
+ if(this.getKeyModifiers(e) == AjaxViewer.SHIFT_KEY_MASK)
+ return true;
+
+ if(this.getKeyModifiers(e) != 0)
+ return false;
+
+ return true;
+ },
+
+ installKeyboardHook: function() {
+ var ajaxViewer = this;
+ var target = $(document);
- ajaxViewer.onMouseUp(pt.x, pt.y, whichButton, modifiers);
- e.stopPropagation();
- return false;
- });
-
- // disable browser right-click context menu
- target.bind("contextmenu", function() { return false; });
- },
-
- uninstallMouseHook : function() {
- var target = $(document);
- target.unbind("mousemove");
- target.unbind("mousedown");
- target.unbind("mouseup");
- target.unbind("contextmenu");
- },
-
- requiresDefaultKeyProcess : function(e) {
- switch(e.which) {
- case 8 : // backspace
- case 9 : // TAB
- case 19 : // PAUSE/BREAK
- case 20 : // CAPSLOCK
- case 27 : // ESCAPE
- case 16 : // SHIFT key
- case 17 : // CTRL key
- case 18 : // ALT key
- case 33 : // PGUP
- case 34 : // PGDN
- case 35 : // END
- case 36 : // HOME
- case 37 : // LEFT
- case 38 : // UP
- case 39 : // RIGHT
- case 40 : // DOWN
- return false;
- }
-
- if(this.getKeyModifiers(e) == AjaxViewer.SHIFT_KEY_MASK)
- return true;
-
- if(this.getKeyModifiers(e) != 0)
- return false;
-
- return true;
- },
-
- installKeyboardHook: function() {
- var ajaxViewer = this;
- var target = $(document);
-
target.keypress(function(e) {
- ajaxViewer.onKeyPress(e.which, ajaxViewer.getKeyModifiers(e));
-
- e.stopPropagation();
- if(ajaxViewer.requiresDefaultKeyProcess(e))
- return true;
-
- e.preventDefault();
- return false;
- });
-
- target.keydown(function(e) {
+ ajaxViewer.onKeyPress(e.which, ajaxViewer.getKeyModifiers(e));
+
+ e.stopPropagation();
+ if(ajaxViewer.requiresDefaultKeyProcess(e))
+ return true;
+
+ e.preventDefault();
+ return false;
+ });
+
+ target.keydown(function(e) {
ajaxViewer.onKeyDown(e.which, ajaxViewer.getKeyModifiers(e));
-
- e.stopPropagation();
- if(ajaxViewer.requiresDefaultKeyProcess(e))
- return true;
-
- e.preventDefault();
- return false;
- });
-
- target.keyup(function(e) {
- ajaxViewer.onKeyUp(e.which, ajaxViewer.getKeyModifiers(e));
-
- e.stopPropagation();
- if(ajaxViewer.requiresDefaultKeyProcess(e))
- return true;
-
- e.preventDefault();
- return false;
- });
- },
-
- uninstallKeyboardHook : function() {
- var target = $(document);
- target.unbind("keypress");
- target.unbind("keydown");
- target.unbind("keyup");
- },
-
- onMouseMove: function(x, y) {
- this.sendMouseEvent(AjaxViewer.MOUSE_MOVE, x, y, 0, 0);
- },
-
- onMouseDown: function(x, y, whichButton, modifiers) {
- this.sendMouseEvent(AjaxViewer.MOUSE_DOWN, x, y, whichButton, modifiers);
- },
-
- onMouseUp: function(x, y, whichButton, modifiers) {
- this.sendMouseEvent(AjaxViewer.MOUSE_UP, x, y, whichButton, modifiers);
-
- var curTick = new Date().getTime();
- if(this.lastClickEvent.time && (curTick - this.lastClickEvent.time < 300)) {
- this.onMouseDblClick(this.lastClickEvent.x, this.lastClickEvent.y,
- this.lastClickEvent.button, this.lastClickEvent.modifiers);
- }
-
- this.lastClickEvent.x = x;
- this.lastClickEvent.y = y;
- this.lastClickEvent.button = whichButton;
- this.lastClickEvent.modifiers = modifiers;
- this.lastClickEvent.time = curTick;
- },
-
- onMouseDblClick: function(x, y, whichButton, modifiers) {
- this.sendMouseEvent(AjaxViewer.MOUSE_DBLCLK, x, y, whichButton, modifiers);
- },
-
+
+ e.stopPropagation();
+ if(ajaxViewer.requiresDefaultKeyProcess(e))
+ return true;
+
+ e.preventDefault();
+ return false;
+ });
+
+ target.keyup(function(e) {
+ ajaxViewer.onKeyUp(e.which, ajaxViewer.getKeyModifiers(e));
+
+ e.stopPropagation();
+ if(ajaxViewer.requiresDefaultKeyProcess(e))
+ return true;
+
+ e.preventDefault();
+ return false;
+ });
+ },
+
+ uninstallKeyboardHook : function() {
+ var target = $(document);
+ target.unbind("keypress");
+ target.unbind("keydown");
+ target.unbind("keyup");
+ },
+
+ onMouseMove: function(x, y) {
+ this.sendMouseEvent(AjaxViewer.MOUSE_MOVE, x, y, 0, 0);
+ },
+
+ onMouseDown: function(x, y, whichButton, modifiers) {
+ this.sendMouseEvent(AjaxViewer.MOUSE_DOWN, x, y, whichButton, modifiers);
+ },
+
+ onMouseUp: function(x, y, whichButton, modifiers) {
+ this.sendMouseEvent(AjaxViewer.MOUSE_UP, x, y, whichButton, modifiers);
+
+ var curTick = new Date().getTime();
+ if(this.lastClickEvent.time && (curTick - this.lastClickEvent.time < 300)) {
+ this.onMouseDblClick(this.lastClickEvent.x, this.lastClickEvent.y,
+ this.lastClickEvent.button, this.lastClickEvent.modifiers);
+ }
+
+ this.lastClickEvent.x = x;
+ this.lastClickEvent.y = y;
+ this.lastClickEvent.button = whichButton;
+ this.lastClickEvent.modifiers = modifiers;
+ this.lastClickEvent.time = curTick;
+ },
+
+ onMouseDblClick: function(x, y, whichButton, modifiers) {
+ this.sendMouseEvent(AjaxViewer.MOUSE_DBLCLK, x, y, whichButton, modifiers);
+ },
+
onKeyPress: function(code, modifiers) {
g_logger.log(Logger.LEVEL_WARN, "RAW KEYBOARD EVENT. KEY-PRESS: " + code + ", modifers: " + modifiers);
this.dispatchKeyboardInput(AjaxViewer.KEY_PRESS, code, modifiers);
- },
-
+ },
+
onKeyDown: function(code, modifiers) {
g_logger.log(Logger.LEVEL_WARN, "RAW KEYBOARD EVENT. KEY-DOWN: " + code + ", modifers: " + modifiers);
this.dispatchKeyboardInput(AjaxViewer.KEY_DOWN, code, modifiers);
- },
-
+ },
+
onKeyUp: function(code, modifiers) {
g_logger.log(Logger.LEVEL_WARN, "RAW KEYBOARD EVENT. KEY-UP: " + code + ", modifers: " + modifiers);
@@ -1308,32 +1308,32 @@ AjaxViewer.prototype = {
break;
}
}
- },
-
- getKeyModifiers: function(e) {
- var modifiers = 0;
- if(e.altKey)
- modifiers |= AjaxViewer.ALT_KEY_MASK;
-
- if(e.altLeft)
- modifiers |= AjaxViewer.LEFT_ALT_MASK;
-
- if(e.ctrlKey)
- modifiers |= AjaxViewer.CTRL_KEY_MASK;
-
- if(e.ctrlLeft)
- modifiers |= AjaxViewer.LEFT_CTRL_MASK;
-
- if(e.shiftKey)
- modifiers |= AjaxViewer.SHIFT_KEY_MASK;
-
- if(e.shiftLeft)
- modifiers |= AjaxViewer.LEFT_SHIFT_MASK;
-
- if(e.metaKey)
- modifiers |= AjaxViewer.META_KEY_MASK;
-
- return modifiers;
- }
-};
+ },
+
+ getKeyModifiers: function(e) {
+ var modifiers = 0;
+ if(e.altKey)
+ modifiers |= AjaxViewer.ALT_KEY_MASK;
+
+ if(e.altLeft)
+ modifiers |= AjaxViewer.LEFT_ALT_MASK;
+
+ if(e.ctrlKey)
+ modifiers |= AjaxViewer.CTRL_KEY_MASK;
+
+ if(e.ctrlLeft)
+ modifiers |= AjaxViewer.LEFT_CTRL_MASK;
+
+ if(e.shiftKey)
+ modifiers |= AjaxViewer.SHIFT_KEY_MASK;
+
+ if(e.shiftLeft)
+ modifiers |= AjaxViewer.LEFT_SHIFT_MASK;
+
+ if(e.metaKey)
+ modifiers |= AjaxViewer.META_KEY_MASK;
+
+ return modifiers;
+ }
+};
diff --git a/console-proxy/scripts/run.bat b/console-proxy/scripts/run.bat
index 39655f9f09f..ce6dc404574 100644
--- a/console-proxy/scripts/run.bat
+++ b/console-proxy/scripts/run.bat
@@ -1,18 +1,18 @@
-rem Licensed to the Apache Software Foundation (ASF) under one
-rem or more contributor license agreements. See the NOTICE file
-rem distributed with this work for additional information
-rem regarding copyright ownership. The ASF licenses this file
-rem to you under the Apache License, Version 2.0 (the
-rem "License"); you may not use this file except in compliance
-rem with the License. You may obtain a copy of the License at
-rem
-rem http://www.apache.org/licenses/LICENSE-2.0
-rem
-rem Unless required by applicable law or agreed to in writing,
-rem software distributed under the License is distributed on an
-rem "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
-rem KIND, either express or implied. See the License for the
-rem specific language governing permissions and limitations
-rem under the License.
-
-java -mx700m -cp cloud-console-proxy.jar;;cloud-console-common.jar;log4j-1.2.15.jar;apache-log4j-extras-1.0.jar;gson-1.3.jar;commons-logging-1.1.1.jar;.;.\conf; com.cloud.consoleproxy.ConsoleProxy %*
+rem Licensed to the Apache Software Foundation (ASF) under one
+rem or more contributor license agreements. See the NOTICE file
+rem distributed with this work for additional information
+rem regarding copyright ownership. The ASF licenses this file
+rem to you under the Apache License, Version 2.0 (the
+rem "License"); you may not use this file except in compliance
+rem with the License. You may obtain a copy of the License at
+rem
+rem http://www.apache.org/licenses/LICENSE-2.0
+rem
+rem Unless required by applicable law or agreed to in writing,
+rem software distributed under the License is distributed on an
+rem "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+rem KIND, either express or implied. See the License for the
+rem specific language governing permissions and limitations
+rem under the License.
+
+java -mx700m -cp cloud-console-proxy.jar;;cloud-console-common.jar;log4j-1.2.15.jar;apache-log4j-extras-1.0.jar;gson-1.3.jar;commons-logging-1.1.1.jar;.;.\conf; com.cloud.consoleproxy.ConsoleProxy %*
diff --git a/console-proxy/src/com/cloud/consoleproxy/AjaxFIFOImageCache.java b/console-proxy/src/com/cloud/consoleproxy/AjaxFIFOImageCache.java
index a745d0d9e81..cff00b3317d 100644
--- a/console-proxy/src/com/cloud/consoleproxy/AjaxFIFOImageCache.java
+++ b/console-proxy/src/com/cloud/consoleproxy/AjaxFIFOImageCache.java
@@ -14,53 +14,53 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-package com.cloud.consoleproxy;
-
-import java.util.ArrayList;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+package com.cloud.consoleproxy;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
import com.cloud.consoleproxy.util.Logger;
-
-public class AjaxFIFOImageCache {
- private static final Logger s_logger = Logger.getLogger(AjaxFIFOImageCache.class);
-
- private List fifoQueue;
- private Map cache;
- private int cacheSize;
+
+public class AjaxFIFOImageCache {
+ private static final Logger s_logger = Logger.getLogger(AjaxFIFOImageCache.class);
+
+ private List fifoQueue;
+ private Map cache;
+ private int cacheSize;
private int nextKey = 0;
-
- public AjaxFIFOImageCache(int cacheSize) {
- this.cacheSize = cacheSize;
- fifoQueue = new ArrayList();
- cache = new HashMap();
- }
-
- public synchronized void clear() {
- fifoQueue.clear();
- cache.clear();
- }
-
- public synchronized int putImage(byte[] image) {
- while(cache.size() >= cacheSize) {
- Integer keyToRemove = fifoQueue.remove(0);
- cache.remove(keyToRemove);
-
- if(s_logger.isTraceEnabled())
- s_logger.trace("Remove image from cache, key: " + keyToRemove);
- }
-
- int key = getNextKey();
-
- if(s_logger.isTraceEnabled())
- s_logger.trace("Add image to cache, key: " + key);
-
- cache.put(key, image);
- fifoQueue.add(key);
- return key;
- }
-
+
+ public AjaxFIFOImageCache(int cacheSize) {
+ this.cacheSize = cacheSize;
+ fifoQueue = new ArrayList();
+ cache = new HashMap();
+ }
+
+ public synchronized void clear() {
+ fifoQueue.clear();
+ cache.clear();
+ }
+
+ public synchronized int putImage(byte[] image) {
+ while(cache.size() >= cacheSize) {
+ Integer keyToRemove = fifoQueue.remove(0);
+ cache.remove(keyToRemove);
+
+ if(s_logger.isTraceEnabled())
+ s_logger.trace("Remove image from cache, key: " + keyToRemove);
+ }
+
+ int key = getNextKey();
+
+ if(s_logger.isTraceEnabled())
+ s_logger.trace("Add image to cache, key: " + key);
+
+ cache.put(key, image);
+ fifoQueue.add(key);
+ return key;
+ }
+
public synchronized byte[] getImage(int key) {
if (key == 0) {
key = nextKey;
diff --git a/console-proxy/src/com/cloud/consoleproxy/AuthenticationException.java b/console-proxy/src/com/cloud/consoleproxy/AuthenticationException.java
index aaf8e44eb0a..3fa266792ae 100644
--- a/console-proxy/src/com/cloud/consoleproxy/AuthenticationException.java
+++ b/console-proxy/src/com/cloud/consoleproxy/AuthenticationException.java
@@ -14,20 +14,20 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-package com.cloud.consoleproxy;
-
-public class AuthenticationException extends Exception {
- private static final long serialVersionUID = -393139302884898842L;
- public AuthenticationException() {
- super();
- }
- public AuthenticationException(String s) {
- super(s);
- }
- public AuthenticationException(String message, Throwable cause) {
- super(message, cause);
- }
- public AuthenticationException(Throwable cause) {
- super(cause);
- }
+package com.cloud.consoleproxy;
+
+public class AuthenticationException extends Exception {
+ private static final long serialVersionUID = -393139302884898842L;
+ public AuthenticationException() {
+ super();
+ }
+ public AuthenticationException(String s) {
+ super(s);
+ }
+ public AuthenticationException(String message, Throwable cause) {
+ super(message, cause);
+ }
+ public AuthenticationException(Throwable cause) {
+ super(cause);
+ }
}
\ No newline at end of file
diff --git a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyAjaxHandler.java b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyAjaxHandler.java
index d91a198a103..6cadeca1f4a 100644
--- a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyAjaxHandler.java
+++ b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyAjaxHandler.java
@@ -14,8 +14,8 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-package com.cloud.consoleproxy;
-
+package com.cloud.consoleproxy;
+
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
@@ -30,377 +30,377 @@ import com.cloud.consoleproxy.util.Logger;
import com.sun.net.httpserver.Headers;
import com.sun.net.httpserver.HttpExchange;
import com.sun.net.httpserver.HttpHandler;
-
-public class ConsoleProxyAjaxHandler implements HttpHandler {
- private static final Logger s_logger = Logger.getLogger(ConsoleProxyAjaxHandler.class);
-
- public ConsoleProxyAjaxHandler() {
- }
-
- public void handle(HttpExchange t) throws IOException {
- try {
- if(s_logger.isTraceEnabled())
- s_logger.trace("AjaxHandler " + t.getRequestURI());
-
- long startTick = System.currentTimeMillis();
-
- doHandle(t);
-
- if(s_logger.isTraceEnabled())
- s_logger.trace(t.getRequestURI() + " process time " + (System.currentTimeMillis() - startTick) + " ms");
- } catch (IOException e) {
- throw e;
- } catch (IllegalArgumentException e) {
- s_logger.warn("Exception, ", e);
- t.sendResponseHeaders(400, -1); // bad request
- } catch(Throwable e) {
- s_logger.error("Unexpected exception, ", e);
- t.sendResponseHeaders(500, -1); // server error
- } finally {
- t.close();
- }
- }
-
- private void doHandle(HttpExchange t) throws Exception, IllegalArgumentException {
- String queries = t.getRequestURI().getQuery();
- if(s_logger.isTraceEnabled())
- s_logger.trace("Handle AJAX request: " + queries);
-
- Map queryMap = ConsoleProxyHttpHandlerHelper.getQueryMap(queries);
-
- String host = queryMap.get("host");
- String portStr = queryMap.get("port");
- String sid = queryMap.get("sid");
- String tag = queryMap.get("tag");
- String ticket = queryMap.get("ticket");
- String ajaxSessionIdStr = queryMap.get("sess");
- String eventStr = queryMap.get("event");
- String console_url = queryMap.get("consoleurl");
- String console_host_session = queryMap.get("sessionref");
-
- if(tag == null)
- tag = "";
-
- long ajaxSessionId = 0;
- int event = 0;
-
- int port;
-
- if(host == null || portStr == null || sid == null)
- throw new IllegalArgumentException();
-
- try {
- port = Integer.parseInt(portStr);
- } catch (NumberFormatException e) {
- s_logger.warn("Invalid number parameter in query string: " + portStr);
- throw new IllegalArgumentException(e);
- }
-
- if(ajaxSessionIdStr != null) {
- try {
- ajaxSessionId = Long.parseLong(ajaxSessionIdStr);
- } catch (NumberFormatException e) {
- s_logger.warn("Invalid number parameter in query string: " + ajaxSessionIdStr);
- throw new IllegalArgumentException(e);
- }
- }
-
- if(eventStr != null) {
- try {
- event = Integer.parseInt(eventStr);
- } catch (NumberFormatException e) {
- s_logger.warn("Invalid number parameter in query string: " + eventStr);
- throw new IllegalArgumentException(e);
- }
- }
-
- ConsoleProxyClient viewer = null;
- try {
- ConsoleProxyClientParam param = new ConsoleProxyClientParam();
- param.setClientHostAddress(host);
- param.setClientHostPort(port);
- param.setClientHostPassword(sid);
- param.setClientTag(tag);
- param.setTicket(ticket);
- param.setClientTunnelUrl(console_url);
- param.setClientTunnelSession(console_host_session);
-
- viewer = ConsoleProxy.getAjaxVncViewer(param, ajaxSessionIdStr);
- } catch(Exception e) {
-
- s_logger.warn("Failed to create viewer due to " + e.getMessage(), e);
-
- String[] content = new String[] {
- "",
- "",
- "
Access is denied for the console session. Please close the window and retry again
",
- "
"
- };
-
- StringBuffer sb = new StringBuffer();
- for(int i = 0; i < content.length; i++)
- sb.append(content[i]);
-
- sendResponse(t, "text/html", sb.toString());
- return;
- }
-
- if(event != 0) {
- if(ajaxSessionId != 0 && ajaxSessionId == viewer.getAjaxSessionId()) {
- if(event == 7) {
- // client send over an event bag
- InputStream is = t.getRequestBody();
- handleClientEventBag(viewer, convertStreamToString(is, true));
- } else {
- handleClientEvent(viewer, event, queryMap);
- }
- sendResponse(t, "text/html", "OK");
- } else {
- if(s_logger.isDebugEnabled())
- s_logger.debug("Ajax request comes from a different session, id in request: " + ajaxSessionId + ", id in viewer: " + viewer.getAjaxSessionId());
-
- sendResponse(t, "text/html", "Invalid ajax client session id");
- }
- } else {
- if(ajaxSessionId != 0 && ajaxSessionId != viewer.getAjaxSessionId()) {
- s_logger.info("Ajax request comes from a different session, id in request: " + ajaxSessionId + ", id in viewer: " + viewer.getAjaxSessionId());
- handleClientKickoff(t, viewer);
- } else if(ajaxSessionId == 0) {
- if(s_logger.isDebugEnabled())
- s_logger.debug("Ajax request indicates a fresh client start");
-
- String title = queryMap.get("t");
- String guest = queryMap.get("guest");
- handleClientStart(t, viewer, title != null ? title : "", guest);
- } else {
-
- if(s_logger.isTraceEnabled())
- s_logger.trace("Ajax request indicates client update");
-
- handleClientUpdate(t, viewer);
- }
- }
- }
-
- private static String convertStreamToString(InputStream is, boolean closeStreamAfterRead) {
- BufferedReader reader = new BufferedReader(new InputStreamReader(is));
- StringBuilder sb = new StringBuilder();
- String line = null;
- try {
- while ((line = reader.readLine()) != null) {
- sb.append(line + "\n");
- }
- } catch (IOException e) {
- s_logger.warn("Exception while reading request body: ", e);
- } finally {
- if(closeStreamAfterRead) {
- try {
- is.close();
- } catch (IOException e) {
- }
- }
- }
- return sb.toString();
- }
-
- private void sendResponse(HttpExchange t, String contentType, String response) throws IOException {
- Headers hds = t.getResponseHeaders();
- hds.set("Content-Type", contentType);
-
- t.sendResponseHeaders(200, response.length());
- OutputStream os = t.getResponseBody();
- try {
- os.write(response.getBytes());
- } finally {
- os.close();
- }
- }
-
- @SuppressWarnings("deprecation")
- private void handleClientEventBag(ConsoleProxyClient viewer, String requestData) {
- if(s_logger.isTraceEnabled())
- s_logger.trace("Handle event bag, event bag: " + requestData);
-
- int start = requestData.indexOf("=");
- if(start < 0)
- start = 0;
- else if(start > 0)
- start++;
- String data = URLDecoder.decode(requestData.substring(start));
- String[] tokens = data.split("\\|");
- if(tokens != null && tokens.length > 0) {
- int count = 0;
- try {
- count = Integer.parseInt(tokens[0]);
- int parsePos = 1;
- int type, event, x, y, code, modifiers;
- for(int i = 0; i < count; i++) {
- type = Integer.parseInt(tokens[parsePos++]);
- if(type == 1) {
- // mouse event
- event = Integer.parseInt(tokens[parsePos++]);
- x = Integer.parseInt(tokens[parsePos++]);
- y = Integer.parseInt(tokens[parsePos++]);
- code = Integer.parseInt(tokens[parsePos++]);
- modifiers = Integer.parseInt(tokens[parsePos++]);
-
- Map queryMap = new HashMap();
- queryMap.put("event", String.valueOf(event));
- queryMap.put("x", String.valueOf(x));
- queryMap.put("y", String.valueOf(y));
- queryMap.put("code", String.valueOf(code));
- queryMap.put("modifier", String.valueOf(modifiers));
- handleClientEvent(viewer, event, queryMap);
- } else {
- // keyboard event
- event = Integer.parseInt(tokens[parsePos++]);
- code = Integer.parseInt(tokens[parsePos++]);
- modifiers = Integer.parseInt(tokens[parsePos++]);
-
- Map queryMap = new HashMap();
- queryMap.put("event", String.valueOf(event));
- queryMap.put("code", String.valueOf(code));
- queryMap.put("modifier", String.valueOf(modifiers));
- handleClientEvent(viewer, event, queryMap);
- }
- }
- } catch(NumberFormatException e) {
- s_logger.warn("Exception in handle client event bag: " + data + ", ", e);
- } catch(Exception e) {
- s_logger.warn("Exception in handle client event bag: " + data + ", ", e);
- } catch(OutOfMemoryError e) {
- s_logger.error("Unrecoverable OutOfMemory Error, exit and let it be re-launched");
- System.exit(1);
- }
- }
- }
-
- private void handleClientEvent(ConsoleProxyClient viewer, int event, Map queryMap) {
- int code = 0;
- int x = 0, y = 0;
- int modifiers = 0;
-
- String str;
- switch(event) {
- case 1: // mouse move
- case 2: // mouse down
- case 3: // mouse up
- case 8: // mouse double click
- str = queryMap.get("x");
- if(str != null) {
- try {
- x = Integer.parseInt(str);
- } catch (NumberFormatException e) {
- s_logger.warn("Invalid number parameter in query string: " + str);
- throw new IllegalArgumentException(e);
- }
- }
- str = queryMap.get("y");
- if(str != null) {
- try {
- y = Integer.parseInt(str);
- } catch (NumberFormatException e) {
- s_logger.warn("Invalid number parameter in query string: " + str);
- throw new IllegalArgumentException(e);
- }
- }
-
- if(event != 1) {
- str = queryMap.get("code");
- try {
- code = Integer.parseInt(str);
- } catch (NumberFormatException e) {
- s_logger.warn("Invalid number parameter in query string: " + str);
- throw new IllegalArgumentException(e);
- }
-
- str = queryMap.get("modifier");
- try {
- modifiers = Integer.parseInt(str);
- } catch (NumberFormatException e) {
- s_logger.warn("Invalid number parameter in query string: " + str);
- throw new IllegalArgumentException(e);
- }
-
- if(s_logger.isTraceEnabled())
- s_logger.trace("Handle client mouse event. event: " + event + ", x: " + x + ", y: " + y + ", button: " + code + ", modifier: " + modifiers);
- } else {
- if(s_logger.isTraceEnabled())
- s_logger.trace("Handle client mouse move event. x: " + x + ", y: " + y);
- }
- viewer.sendClientMouseEvent(InputEventType.fromEventCode(event), x, y, code, modifiers);
- break;
-
- case 4: // key press
- case 5: // key down
- case 6: // key up
- str = queryMap.get("code");
- try {
- code = Integer.parseInt(str);
- } catch (NumberFormatException e) {
- s_logger.warn("Invalid number parameter in query string: " + str);
- throw new IllegalArgumentException(e);
- }
-
- str = queryMap.get("modifier");
- try {
- modifiers = Integer.parseInt(str);
- } catch (NumberFormatException e) {
- s_logger.warn("Invalid number parameter in query string: " + str);
- throw new IllegalArgumentException(e);
- }
-
- if(s_logger.isDebugEnabled())
- s_logger.debug("Handle client keyboard event. event: " + event + ", code: " + code + ", modifier: " + modifiers);
- viewer.sendClientRawKeyboardEvent(InputEventType.fromEventCode(event), code, modifiers);
- break;
-
- default :
- break;
- }
- }
-
- private void handleClientKickoff(HttpExchange t, ConsoleProxyClient viewer) throws IOException {
- String response = viewer.onAjaxClientKickoff();
- t.sendResponseHeaders(200, response.length());
- OutputStream os = t.getResponseBody();
- try {
- os.write(response.getBytes());
- } finally {
- os.close();
- }
- }
-
- private void handleClientStart(HttpExchange t, ConsoleProxyClient viewer, String title, String guest) throws IOException {
- List languages = t.getRequestHeaders().get("Accept-Language");
- String response = viewer.onAjaxClientStart(title, languages, guest);
-
- Headers hds = t.getResponseHeaders();
- hds.set("Content-Type", "text/html");
- hds.set("Cache-Control", "no-cache");
- hds.set("Cache-Control", "no-store");
- t.sendResponseHeaders(200, response.length());
-
- OutputStream os = t.getResponseBody();
- try {
- os.write(response.getBytes());
- } finally {
- os.close();
- }
- }
-
- private void handleClientUpdate(HttpExchange t, ConsoleProxyClient viewer) throws IOException {
- String response = viewer.onAjaxClientUpdate();
-
- Headers hds = t.getResponseHeaders();
- hds.set("Content-Type", "text/javascript");
- t.sendResponseHeaders(200, response.length());
-
- OutputStream os = t.getResponseBody();
- try {
- os.write(response.getBytes());
- } finally {
- os.close();
- }
- }
-}
+
+public class ConsoleProxyAjaxHandler implements HttpHandler {
+ private static final Logger s_logger = Logger.getLogger(ConsoleProxyAjaxHandler.class);
+
+ public ConsoleProxyAjaxHandler() {
+ }
+
+ public void handle(HttpExchange t) throws IOException {
+ try {
+ if(s_logger.isTraceEnabled())
+ s_logger.trace("AjaxHandler " + t.getRequestURI());
+
+ long startTick = System.currentTimeMillis();
+
+ doHandle(t);
+
+ if(s_logger.isTraceEnabled())
+ s_logger.trace(t.getRequestURI() + " process time " + (System.currentTimeMillis() - startTick) + " ms");
+ } catch (IOException e) {
+ throw e;
+ } catch (IllegalArgumentException e) {
+ s_logger.warn("Exception, ", e);
+ t.sendResponseHeaders(400, -1); // bad request
+ } catch(Throwable e) {
+ s_logger.error("Unexpected exception, ", e);
+ t.sendResponseHeaders(500, -1); // server error
+ } finally {
+ t.close();
+ }
+ }
+
+ private void doHandle(HttpExchange t) throws Exception, IllegalArgumentException {
+ String queries = t.getRequestURI().getQuery();
+ if(s_logger.isTraceEnabled())
+ s_logger.trace("Handle AJAX request: " + queries);
+
+ Map queryMap = ConsoleProxyHttpHandlerHelper.getQueryMap(queries);
+
+ String host = queryMap.get("host");
+ String portStr = queryMap.get("port");
+ String sid = queryMap.get("sid");
+ String tag = queryMap.get("tag");
+ String ticket = queryMap.get("ticket");
+ String ajaxSessionIdStr = queryMap.get("sess");
+ String eventStr = queryMap.get("event");
+ String console_url = queryMap.get("consoleurl");
+ String console_host_session = queryMap.get("sessionref");
+
+ if(tag == null)
+ tag = "";
+
+ long ajaxSessionId = 0;
+ int event = 0;
+
+ int port;
+
+ if(host == null || portStr == null || sid == null)
+ throw new IllegalArgumentException();
+
+ try {
+ port = Integer.parseInt(portStr);
+ } catch (NumberFormatException e) {
+ s_logger.warn("Invalid number parameter in query string: " + portStr);
+ throw new IllegalArgumentException(e);
+ }
+
+ if(ajaxSessionIdStr != null) {
+ try {
+ ajaxSessionId = Long.parseLong(ajaxSessionIdStr);
+ } catch (NumberFormatException e) {
+ s_logger.warn("Invalid number parameter in query string: " + ajaxSessionIdStr);
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ if(eventStr != null) {
+ try {
+ event = Integer.parseInt(eventStr);
+ } catch (NumberFormatException e) {
+ s_logger.warn("Invalid number parameter in query string: " + eventStr);
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ ConsoleProxyClient viewer = null;
+ try {
+ ConsoleProxyClientParam param = new ConsoleProxyClientParam();
+ param.setClientHostAddress(host);
+ param.setClientHostPort(port);
+ param.setClientHostPassword(sid);
+ param.setClientTag(tag);
+ param.setTicket(ticket);
+ param.setClientTunnelUrl(console_url);
+ param.setClientTunnelSession(console_host_session);
+
+ viewer = ConsoleProxy.getAjaxVncViewer(param, ajaxSessionIdStr);
+ } catch(Exception e) {
+
+ s_logger.warn("Failed to create viewer due to " + e.getMessage(), e);
+
+ String[] content = new String[] {
+ "",
+ "",
+ "
Access is denied for the console session. Please close the window and retry again
",
+ "
"
+ };
+
+ StringBuffer sb = new StringBuffer();
+ for(int i = 0; i < content.length; i++)
+ sb.append(content[i]);
+
+ sendResponse(t, "text/html", sb.toString());
+ return;
+ }
+
+ if(event != 0) {
+ if(ajaxSessionId != 0 && ajaxSessionId == viewer.getAjaxSessionId()) {
+ if(event == 7) {
+ // client send over an event bag
+ InputStream is = t.getRequestBody();
+ handleClientEventBag(viewer, convertStreamToString(is, true));
+ } else {
+ handleClientEvent(viewer, event, queryMap);
+ }
+ sendResponse(t, "text/html", "OK");
+ } else {
+ if(s_logger.isDebugEnabled())
+ s_logger.debug("Ajax request comes from a different session, id in request: " + ajaxSessionId + ", id in viewer: " + viewer.getAjaxSessionId());
+
+ sendResponse(t, "text/html", "Invalid ajax client session id");
+ }
+ } else {
+ if(ajaxSessionId != 0 && ajaxSessionId != viewer.getAjaxSessionId()) {
+ s_logger.info("Ajax request comes from a different session, id in request: " + ajaxSessionId + ", id in viewer: " + viewer.getAjaxSessionId());
+ handleClientKickoff(t, viewer);
+ } else if(ajaxSessionId == 0) {
+ if(s_logger.isDebugEnabled())
+ s_logger.debug("Ajax request indicates a fresh client start");
+
+ String title = queryMap.get("t");
+ String guest = queryMap.get("guest");
+ handleClientStart(t, viewer, title != null ? title : "", guest);
+ } else {
+
+ if(s_logger.isTraceEnabled())
+ s_logger.trace("Ajax request indicates client update");
+
+ handleClientUpdate(t, viewer);
+ }
+ }
+ }
+
+ private static String convertStreamToString(InputStream is, boolean closeStreamAfterRead) {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(is));
+ StringBuilder sb = new StringBuilder();
+ String line = null;
+ try {
+ while ((line = reader.readLine()) != null) {
+ sb.append(line + "\n");
+ }
+ } catch (IOException e) {
+ s_logger.warn("Exception while reading request body: ", e);
+ } finally {
+ if(closeStreamAfterRead) {
+ try {
+ is.close();
+ } catch (IOException e) {
+ }
+ }
+ }
+ return sb.toString();
+ }
+
+ private void sendResponse(HttpExchange t, String contentType, String response) throws IOException {
+ Headers hds = t.getResponseHeaders();
+ hds.set("Content-Type", contentType);
+
+ t.sendResponseHeaders(200, response.length());
+ OutputStream os = t.getResponseBody();
+ try {
+ os.write(response.getBytes());
+ } finally {
+ os.close();
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ private void handleClientEventBag(ConsoleProxyClient viewer, String requestData) {
+ if(s_logger.isTraceEnabled())
+ s_logger.trace("Handle event bag, event bag: " + requestData);
+
+ int start = requestData.indexOf("=");
+ if(start < 0)
+ start = 0;
+ else if(start > 0)
+ start++;
+ String data = URLDecoder.decode(requestData.substring(start));
+ String[] tokens = data.split("\\|");
+ if(tokens != null && tokens.length > 0) {
+ int count = 0;
+ try {
+ count = Integer.parseInt(tokens[0]);
+ int parsePos = 1;
+ int type, event, x, y, code, modifiers;
+ for(int i = 0; i < count; i++) {
+ type = Integer.parseInt(tokens[parsePos++]);
+ if(type == 1) {
+ // mouse event
+ event = Integer.parseInt(tokens[parsePos++]);
+ x = Integer.parseInt(tokens[parsePos++]);
+ y = Integer.parseInt(tokens[parsePos++]);
+ code = Integer.parseInt(tokens[parsePos++]);
+ modifiers = Integer.parseInt(tokens[parsePos++]);
+
+ Map queryMap = new HashMap();
+ queryMap.put("event", String.valueOf(event));
+ queryMap.put("x", String.valueOf(x));
+ queryMap.put("y", String.valueOf(y));
+ queryMap.put("code", String.valueOf(code));
+ queryMap.put("modifier", String.valueOf(modifiers));
+ handleClientEvent(viewer, event, queryMap);
+ } else {
+ // keyboard event
+ event = Integer.parseInt(tokens[parsePos++]);
+ code = Integer.parseInt(tokens[parsePos++]);
+ modifiers = Integer.parseInt(tokens[parsePos++]);
+
+ Map queryMap = new HashMap();
+ queryMap.put("event", String.valueOf(event));
+ queryMap.put("code", String.valueOf(code));
+ queryMap.put("modifier", String.valueOf(modifiers));
+ handleClientEvent(viewer, event, queryMap);
+ }
+ }
+ } catch(NumberFormatException e) {
+ s_logger.warn("Exception in handle client event bag: " + data + ", ", e);
+ } catch(Exception e) {
+ s_logger.warn("Exception in handle client event bag: " + data + ", ", e);
+ } catch(OutOfMemoryError e) {
+ s_logger.error("Unrecoverable OutOfMemory Error, exit and let it be re-launched");
+ System.exit(1);
+ }
+ }
+ }
+
+ private void handleClientEvent(ConsoleProxyClient viewer, int event, Map queryMap) {
+ int code = 0;
+ int x = 0, y = 0;
+ int modifiers = 0;
+
+ String str;
+ switch(event) {
+ case 1: // mouse move
+ case 2: // mouse down
+ case 3: // mouse up
+ case 8: // mouse double click
+ str = queryMap.get("x");
+ if(str != null) {
+ try {
+ x = Integer.parseInt(str);
+ } catch (NumberFormatException e) {
+ s_logger.warn("Invalid number parameter in query string: " + str);
+ throw new IllegalArgumentException(e);
+ }
+ }
+ str = queryMap.get("y");
+ if(str != null) {
+ try {
+ y = Integer.parseInt(str);
+ } catch (NumberFormatException e) {
+ s_logger.warn("Invalid number parameter in query string: " + str);
+ throw new IllegalArgumentException(e);
+ }
+ }
+
+ if(event != 1) {
+ str = queryMap.get("code");
+ try {
+ code = Integer.parseInt(str);
+ } catch (NumberFormatException e) {
+ s_logger.warn("Invalid number parameter in query string: " + str);
+ throw new IllegalArgumentException(e);
+ }
+
+ str = queryMap.get("modifier");
+ try {
+ modifiers = Integer.parseInt(str);
+ } catch (NumberFormatException e) {
+ s_logger.warn("Invalid number parameter in query string: " + str);
+ throw new IllegalArgumentException(e);
+ }
+
+ if(s_logger.isTraceEnabled())
+ s_logger.trace("Handle client mouse event. event: " + event + ", x: " + x + ", y: " + y + ", button: " + code + ", modifier: " + modifiers);
+ } else {
+ if(s_logger.isTraceEnabled())
+ s_logger.trace("Handle client mouse move event. x: " + x + ", y: " + y);
+ }
+ viewer.sendClientMouseEvent(InputEventType.fromEventCode(event), x, y, code, modifiers);
+ break;
+
+ case 4: // key press
+ case 5: // key down
+ case 6: // key up
+ str = queryMap.get("code");
+ try {
+ code = Integer.parseInt(str);
+ } catch (NumberFormatException e) {
+ s_logger.warn("Invalid number parameter in query string: " + str);
+ throw new IllegalArgumentException(e);
+ }
+
+ str = queryMap.get("modifier");
+ try {
+ modifiers = Integer.parseInt(str);
+ } catch (NumberFormatException e) {
+ s_logger.warn("Invalid number parameter in query string: " + str);
+ throw new IllegalArgumentException(e);
+ }
+
+ if(s_logger.isDebugEnabled())
+ s_logger.debug("Handle client keyboard event. event: " + event + ", code: " + code + ", modifier: " + modifiers);
+ viewer.sendClientRawKeyboardEvent(InputEventType.fromEventCode(event), code, modifiers);
+ break;
+
+ default :
+ break;
+ }
+ }
+
+ private void handleClientKickoff(HttpExchange t, ConsoleProxyClient viewer) throws IOException {
+ String response = viewer.onAjaxClientKickoff();
+ t.sendResponseHeaders(200, response.length());
+ OutputStream os = t.getResponseBody();
+ try {
+ os.write(response.getBytes());
+ } finally {
+ os.close();
+ }
+ }
+
+ private void handleClientStart(HttpExchange t, ConsoleProxyClient viewer, String title, String guest) throws IOException {
+ List languages = t.getRequestHeaders().get("Accept-Language");
+ String response = viewer.onAjaxClientStart(title, languages, guest);
+
+ Headers hds = t.getResponseHeaders();
+ hds.set("Content-Type", "text/html");
+ hds.set("Cache-Control", "no-cache");
+ hds.set("Cache-Control", "no-store");
+ t.sendResponseHeaders(200, response.length());
+
+ OutputStream os = t.getResponseBody();
+ try {
+ os.write(response.getBytes());
+ } finally {
+ os.close();
+ }
+ }
+
+ private void handleClientUpdate(HttpExchange t, ConsoleProxyClient viewer) throws IOException {
+ String response = viewer.onAjaxClientUpdate();
+
+ Headers hds = t.getResponseHeaders();
+ hds.set("Content-Type", "text/javascript");
+ t.sendResponseHeaders(200, response.length());
+
+ OutputStream os = t.getResponseBody();
+ try {
+ os.write(response.getBytes());
+ } finally {
+ os.close();
+ }
+ }
+}
diff --git a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyAjaxImageHandler.java b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyAjaxImageHandler.java
index 9c0094839cf..5e1014963f3 100644
--- a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyAjaxImageHandler.java
+++ b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyAjaxImageHandler.java
@@ -14,87 +14,87 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-package com.cloud.consoleproxy;
-
+package com.cloud.consoleproxy;
+
import java.awt.Graphics2D;
import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Map;
-
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Map;
+
import com.cloud.consoleproxy.util.Logger;
-import com.sun.net.httpserver.Headers;
-import com.sun.net.httpserver.HttpExchange;
-import com.sun.net.httpserver.HttpHandler;
-
-public class ConsoleProxyAjaxImageHandler implements HttpHandler {
- private static final Logger s_logger = Logger.getLogger(ConsoleProxyAjaxImageHandler.class);
-
- public void handle(HttpExchange t) throws IOException {
- try {
- if(s_logger.isDebugEnabled())
- s_logger.debug("AjaxImageHandler " + t.getRequestURI());
-
- long startTick = System.currentTimeMillis();
-
- doHandle(t);
-
- if(s_logger.isDebugEnabled())
- s_logger.debug(t.getRequestURI() + "Process time " + (System.currentTimeMillis() - startTick) + " ms");
- } catch (IOException e) {
- throw e;
- } catch (IllegalArgumentException e) {
- s_logger.warn("Exception, ", e);
- t.sendResponseHeaders(400, -1); // bad request
- } catch(OutOfMemoryError e) {
- s_logger.error("Unrecoverable OutOfMemory Error, exit and let it be re-launched");
- System.exit(1);
- } catch(Throwable e) {
- s_logger.error("Unexpected exception, ", e);
- t.sendResponseHeaders(500, -1); // server error
- } finally {
- t.close();
- }
- }
-
- private void doHandle(HttpExchange t) throws Exception, IllegalArgumentException {
- String queries = t.getRequestURI().getQuery();
- Map queryMap = ConsoleProxyHttpHandlerHelper.getQueryMap(queries);
-
- String host = queryMap.get("host");
- String portStr = queryMap.get("port");
- String sid = queryMap.get("sid");
- String tag = queryMap.get("tag");
- String ticket = queryMap.get("ticket");
- String keyStr = queryMap.get("key");
- String console_url = queryMap.get("consoleurl");
- String console_host_session = queryMap.get("sessionref");
- String w = queryMap.get("w");
+import com.sun.net.httpserver.Headers;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+
+public class ConsoleProxyAjaxImageHandler implements HttpHandler {
+ private static final Logger s_logger = Logger.getLogger(ConsoleProxyAjaxImageHandler.class);
+
+ public void handle(HttpExchange t) throws IOException {
+ try {
+ if(s_logger.isDebugEnabled())
+ s_logger.debug("AjaxImageHandler " + t.getRequestURI());
+
+ long startTick = System.currentTimeMillis();
+
+ doHandle(t);
+
+ if(s_logger.isDebugEnabled())
+ s_logger.debug(t.getRequestURI() + "Process time " + (System.currentTimeMillis() - startTick) + " ms");
+ } catch (IOException e) {
+ throw e;
+ } catch (IllegalArgumentException e) {
+ s_logger.warn("Exception, ", e);
+ t.sendResponseHeaders(400, -1); // bad request
+ } catch(OutOfMemoryError e) {
+ s_logger.error("Unrecoverable OutOfMemory Error, exit and let it be re-launched");
+ System.exit(1);
+ } catch(Throwable e) {
+ s_logger.error("Unexpected exception, ", e);
+ t.sendResponseHeaders(500, -1); // server error
+ } finally {
+ t.close();
+ }
+ }
+
+ private void doHandle(HttpExchange t) throws Exception, IllegalArgumentException {
+ String queries = t.getRequestURI().getQuery();
+ Map queryMap = ConsoleProxyHttpHandlerHelper.getQueryMap(queries);
+
+ String host = queryMap.get("host");
+ String portStr = queryMap.get("port");
+ String sid = queryMap.get("sid");
+ String tag = queryMap.get("tag");
+ String ticket = queryMap.get("ticket");
+ String keyStr = queryMap.get("key");
+ String console_url = queryMap.get("consoleurl");
+ String console_host_session = queryMap.get("sessionref");
+ String w = queryMap.get("w");
String h = queryMap.get("h");
-
+
int key = 0;
int width = 144;
int height = 110;
-
- if(tag == null)
- tag = "";
-
- int port;
- if(host == null || portStr == null || sid == null)
- throw new IllegalArgumentException();
-
- try {
- port = Integer.parseInt(portStr);
- } catch (NumberFormatException e) {
- s_logger.warn("Invalid numeric parameter in query string: " + portStr);
- throw new IllegalArgumentException(e);
- }
-
- try {
+
+ if(tag == null)
+ tag = "";
+
+ int port;
+ if(host == null || portStr == null || sid == null)
+ throw new IllegalArgumentException();
+
+ try {
+ port = Integer.parseInt(portStr);
+ } catch (NumberFormatException e) {
+ s_logger.warn("Invalid numeric parameter in query string: " + portStr);
+ throw new IllegalArgumentException(e);
+ }
+
+ try {
if (keyStr != null)
- key = Integer.parseInt(keyStr);
+ key = Integer.parseInt(keyStr);
if(null != w)
width = Integer.parseInt(w);
@@ -102,58 +102,58 @@ public class ConsoleProxyAjaxImageHandler implements HttpHandler {
height = Integer.parseInt(h);
} catch (NumberFormatException e) {
- s_logger.warn("Invalid numeric parameter in query string: " + keyStr);
- throw new IllegalArgumentException(e);
- }
+ s_logger.warn("Invalid numeric parameter in query string: " + keyStr);
+ throw new IllegalArgumentException(e);
+ }
- ConsoleProxyClientParam param = new ConsoleProxyClientParam();
- param.setClientHostAddress(host);
- param.setClientHostPort(port);
- param.setClientHostPassword(sid);
- param.setClientTag(tag);
- param.setTicket(ticket);
- param.setClientTunnelUrl(console_url);
- param.setClientTunnelSession(console_host_session);
+ ConsoleProxyClientParam param = new ConsoleProxyClientParam();
+ param.setClientHostAddress(host);
+ param.setClientHostPort(port);
+ param.setClientHostPassword(sid);
+ param.setClientTag(tag);
+ param.setTicket(ticket);
+ param.setClientTunnelUrl(console_url);
+ param.setClientTunnelSession(console_host_session);
- ConsoleProxyClient viewer = ConsoleProxy.getVncViewer(param);
+ ConsoleProxyClient viewer = ConsoleProxy.getVncViewer(param);
- if (key == 0) {
- Image scaledImage = viewer.getClientScaledImage(width, height);
- BufferedImage bufferedImage = new BufferedImage(width, height,
- BufferedImage.TYPE_3BYTE_BGR);
- Graphics2D bufImageGraphics = bufferedImage.createGraphics();
- bufImageGraphics.drawImage(scaledImage, 0, 0, null);
- ByteArrayOutputStream bos = new ByteArrayOutputStream(8196);
- javax.imageio.ImageIO.write(bufferedImage, "jpg", bos);
- byte[] bs = bos.toByteArray();
- Headers hds = t.getResponseHeaders();
- hds.set("Content-Type", "image/jpeg");
- hds.set("Cache-Control", "no-cache");
- hds.set("Cache-Control", "no-store");
- t.sendResponseHeaders(200, bs.length);
- OutputStream os = t.getResponseBody();
- os.write(bs);
- os.close();
- } else {
- AjaxFIFOImageCache imageCache = viewer.getAjaxImageCache();
- byte[] img = imageCache.getImage(key);
-
- if(img != null) {
- Headers hds = t.getResponseHeaders();
- hds.set("Content-Type", "image/jpeg");
- t.sendResponseHeaders(200, img.length);
-
- OutputStream os = t.getResponseBody();
- try {
- os.write(img, 0, img.length);
- } finally {
- os.close();
- }
- } else {
- if(s_logger.isInfoEnabled())
- s_logger.info("Image has already been swept out, key: " + key);
- t.sendResponseHeaders(404, -1);
- }
- }
- }
-}
+ if (key == 0) {
+ Image scaledImage = viewer.getClientScaledImage(width, height);
+ BufferedImage bufferedImage = new BufferedImage(width, height,
+ BufferedImage.TYPE_3BYTE_BGR);
+ Graphics2D bufImageGraphics = bufferedImage.createGraphics();
+ bufImageGraphics.drawImage(scaledImage, 0, 0, null);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream(8196);
+ javax.imageio.ImageIO.write(bufferedImage, "jpg", bos);
+ byte[] bs = bos.toByteArray();
+ Headers hds = t.getResponseHeaders();
+ hds.set("Content-Type", "image/jpeg");
+ hds.set("Cache-Control", "no-cache");
+ hds.set("Cache-Control", "no-store");
+ t.sendResponseHeaders(200, bs.length);
+ OutputStream os = t.getResponseBody();
+ os.write(bs);
+ os.close();
+ } else {
+ AjaxFIFOImageCache imageCache = viewer.getAjaxImageCache();
+ byte[] img = imageCache.getImage(key);
+
+ if(img != null) {
+ Headers hds = t.getResponseHeaders();
+ hds.set("Content-Type", "image/jpeg");
+ t.sendResponseHeaders(200, img.length);
+
+ OutputStream os = t.getResponseBody();
+ try {
+ os.write(img, 0, img.length);
+ } finally {
+ os.close();
+ }
+ } else {
+ if(s_logger.isInfoEnabled())
+ s_logger.info("Image has already been swept out, key: " + key);
+ t.sendResponseHeaders(404, -1);
+ }
+ }
+ }
+}
diff --git a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyAuthenticationResult.java b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyAuthenticationResult.java
index d9563b94d97..26ee9b33155 100644
--- a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyAuthenticationResult.java
+++ b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyAuthenticationResult.java
@@ -14,68 +14,68 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-package com.cloud.consoleproxy;
-
-// duplicated class
-public class ConsoleProxyAuthenticationResult {
- private boolean success;
- private boolean isReauthentication;
- private String host;
- private int port;
- private String tunnelUrl;
- private String tunnelSession;
-
- public ConsoleProxyAuthenticationResult() {
- success = false;
- isReauthentication = false;
- port = 0;
- }
-
- public boolean isSuccess() {
- return success;
- }
-
- public void setSuccess(boolean success) {
- this.success = success;
- }
-
- public boolean isReauthentication() {
- return isReauthentication;
- }
-
- public void setReauthentication(boolean isReauthentication) {
- this.isReauthentication = isReauthentication;
- }
-
- public String getHost() {
- return host;
- }
-
- public void setHost(String host) {
- this.host = host;
- }
-
- public int getPort() {
- return port;
- }
-
- public void setPort(int port) {
- this.port = port;
- }
-
- public String getTunnelUrl() {
- return tunnelUrl;
- }
-
- public void setTunnelUrl(String tunnelUrl) {
- this.tunnelUrl = tunnelUrl;
- }
-
- public String getTunnelSession() {
- return tunnelSession;
- }
-
- public void setTunnelSession(String tunnelSession) {
- this.tunnelSession = tunnelSession;
- }
-}
+package com.cloud.consoleproxy;
+
+// duplicated class
+public class ConsoleProxyAuthenticationResult {
+ private boolean success;
+ private boolean isReauthentication;
+ private String host;
+ private int port;
+ private String tunnelUrl;
+ private String tunnelSession;
+
+ public ConsoleProxyAuthenticationResult() {
+ success = false;
+ isReauthentication = false;
+ port = 0;
+ }
+
+ public boolean isSuccess() {
+ return success;
+ }
+
+ public void setSuccess(boolean success) {
+ this.success = success;
+ }
+
+ public boolean isReauthentication() {
+ return isReauthentication;
+ }
+
+ public void setReauthentication(boolean isReauthentication) {
+ this.isReauthentication = isReauthentication;
+ }
+
+ public String getHost() {
+ return host;
+ }
+
+ public void setHost(String host) {
+ this.host = host;
+ }
+
+ public int getPort() {
+ return port;
+ }
+
+ public void setPort(int port) {
+ this.port = port;
+ }
+
+ public String getTunnelUrl() {
+ return tunnelUrl;
+ }
+
+ public void setTunnelUrl(String tunnelUrl) {
+ this.tunnelUrl = tunnelUrl;
+ }
+
+ public String getTunnelSession() {
+ return tunnelSession;
+ }
+
+ public void setTunnelSession(String tunnelSession) {
+ this.tunnelSession = tunnelSession;
+ }
+}
diff --git a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyBaseServerFactoryImpl.java b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyBaseServerFactoryImpl.java
index 2706184a72e..c9ad8ab82fa 100644
--- a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyBaseServerFactoryImpl.java
+++ b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyBaseServerFactoryImpl.java
@@ -14,8 +14,8 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-package com.cloud.consoleproxy;
-
+package com.cloud.consoleproxy;
+
import java.io.IOException;
import java.net.InetSocketAddress;
@@ -23,26 +23,26 @@ import javax.net.ssl.SSLServerSocket;
import com.cloud.consoleproxy.util.Logger;
import com.sun.net.httpserver.HttpServer;
-
-public class ConsoleProxyBaseServerFactoryImpl implements ConsoleProxyServerFactory {
- private static final Logger s_logger = Logger.getLogger(ConsoleProxyBaseServerFactoryImpl.class);
-
- @Override
- public void init(byte[] ksBits, String ksPassword) {
- }
-
- @Override
- public HttpServer createHttpServerInstance(int port) throws IOException {
- if(s_logger.isInfoEnabled())
- s_logger.info("create HTTP server instance at port: " + port);
- return HttpServer.create(new InetSocketAddress(port), 5);
- }
-
- @Override
- public SSLServerSocket createSSLServerSocket(int port) throws IOException {
- if(s_logger.isInfoEnabled())
- s_logger.info("SSL server socket is not supported in ConsoleProxyBaseServerFactoryImpl");
-
- return null;
- }
-}
+
+public class ConsoleProxyBaseServerFactoryImpl implements ConsoleProxyServerFactory {
+ private static final Logger s_logger = Logger.getLogger(ConsoleProxyBaseServerFactoryImpl.class);
+
+ @Override
+ public void init(byte[] ksBits, String ksPassword) {
+ }
+
+ @Override
+ public HttpServer createHttpServerInstance(int port) throws IOException {
+ if(s_logger.isInfoEnabled())
+ s_logger.info("create HTTP server instance at port: " + port);
+ return HttpServer.create(new InetSocketAddress(port), 5);
+ }
+
+ @Override
+ public SSLServerSocket createSSLServerSocket(int port) throws IOException {
+ if(s_logger.isInfoEnabled())
+ s_logger.info("SSL server socket is not supported in ConsoleProxyBaseServerFactoryImpl");
+
+ return null;
+ }
+}
diff --git a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClientListener.java b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClientListener.java
index 89097d84af7..43a0bab8bed 100644
--- a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClientListener.java
+++ b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClientListener.java
@@ -14,12 +14,12 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-package com.cloud.consoleproxy;
-
-public interface ConsoleProxyClientListener {
- void onFramebufferSizeChange(int w, int h);
- void onFramebufferUpdate(int x, int y, int w, int h);
-
- void onClientConnected();
- void onClientClose();
-}
+package com.cloud.consoleproxy;
+
+public interface ConsoleProxyClientListener {
+ void onFramebufferSizeChange(int w, int h);
+ void onFramebufferUpdate(int x, int y, int w, int h);
+
+ void onClientConnected();
+ void onClientClose();
+}
diff --git a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyCmdHandler.java b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyCmdHandler.java
index 5471dea148f..408eb0419d7 100644
--- a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyCmdHandler.java
+++ b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyCmdHandler.java
@@ -14,57 +14,57 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-package com.cloud.consoleproxy;
-
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.OutputStreamWriter;
-
+package com.cloud.consoleproxy;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+
import com.cloud.consoleproxy.util.Logger;
-import com.sun.net.httpserver.Headers;
-import com.sun.net.httpserver.HttpExchange;
-import com.sun.net.httpserver.HttpHandler;
-
-public class ConsoleProxyCmdHandler implements HttpHandler {
- private static final Logger s_logger = Logger.getLogger(ConsoleProxyCmdHandler.class);
-
- public void handle(HttpExchange t) throws IOException {
- try {
- Thread.currentThread().setName("Cmd Thread " +
- Thread.currentThread().getId() + " " + t.getRemoteAddress());
- s_logger.info("CmdHandler " + t.getRequestURI());
- doHandle(t);
- } catch (Exception e) {
- s_logger.error(e.toString(), e);
- String response = "Not found";
- t.sendResponseHeaders(404, response.length());
- OutputStream os = t.getResponseBody();
- os.write(response.getBytes());
- os.close();
- } catch(OutOfMemoryError e) {
- s_logger.error("Unrecoverable OutOfMemory Error, exit and let it be re-launched");
- System.exit(1);
- } catch (Throwable e) {
- s_logger.error(e.toString(), e);
- } finally {
- t.close();
- }
- }
-
- public void doHandle(HttpExchange t) throws Exception {
- String path = t.getRequestURI().getPath();
- int i = path.indexOf("/", 1);
- String cmd = path.substring(i + 1);
- s_logger.info("Get CMD request for " + cmd);
- if (cmd.equals("getstatus")) {
- ConsoleProxyClientStatsCollector statsCollector = ConsoleProxy.getStatsCollector();
-
- Headers hds = t.getResponseHeaders();
- hds.set("Content-Type", "text/plain");
- t.sendResponseHeaders(200, 0);
- OutputStreamWriter os = new OutputStreamWriter(t.getResponseBody());
- statsCollector.getStatsReport(os);
- os.close();
- }
- }
-}
+import com.sun.net.httpserver.Headers;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+
+public class ConsoleProxyCmdHandler implements HttpHandler {
+ private static final Logger s_logger = Logger.getLogger(ConsoleProxyCmdHandler.class);
+
+ public void handle(HttpExchange t) throws IOException {
+ try {
+ Thread.currentThread().setName("Cmd Thread " +
+ Thread.currentThread().getId() + " " + t.getRemoteAddress());
+ s_logger.info("CmdHandler " + t.getRequestURI());
+ doHandle(t);
+ } catch (Exception e) {
+ s_logger.error(e.toString(), e);
+ String response = "Not found";
+ t.sendResponseHeaders(404, response.length());
+ OutputStream os = t.getResponseBody();
+ os.write(response.getBytes());
+ os.close();
+ } catch(OutOfMemoryError e) {
+ s_logger.error("Unrecoverable OutOfMemory Error, exit and let it be re-launched");
+ System.exit(1);
+ } catch (Throwable e) {
+ s_logger.error(e.toString(), e);
+ } finally {
+ t.close();
+ }
+ }
+
+ public void doHandle(HttpExchange t) throws Exception {
+ String path = t.getRequestURI().getPath();
+ int i = path.indexOf("/", 1);
+ String cmd = path.substring(i + 1);
+ s_logger.info("Get CMD request for " + cmd);
+ if (cmd.equals("getstatus")) {
+ ConsoleProxyClientStatsCollector statsCollector = ConsoleProxy.getStatsCollector();
+
+ Headers hds = t.getResponseHeaders();
+ hds.set("Content-Type", "text/plain");
+ t.sendResponseHeaders(200, 0);
+ OutputStreamWriter os = new OutputStreamWriter(t.getResponseBody());
+ statsCollector.getStatsReport(os);
+ os.close();
+ }
+ }
+}
diff --git a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyHttpHandlerHelper.java b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyHttpHandlerHelper.java
index cf2027b86ec..7756d01cd7f 100644
--- a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyHttpHandlerHelper.java
+++ b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyHttpHandlerHelper.java
@@ -14,61 +14,61 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-package com.cloud.consoleproxy;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import com.cloud.consoleproxy.util.Logger;
-
-public class ConsoleProxyHttpHandlerHelper {
- private static final Logger s_logger = Logger.getLogger(ConsoleProxyHttpHandlerHelper.class);
-
- public static Map getQueryMap(String query) {
- String[] params = query.split("&");
- Map map = new HashMap();
- for (String param : params) {
- String[] paramTokens = param.split("=");
- if(paramTokens != null && paramTokens.length == 2) {
- String name = param.split("=")[0];
- String value = param.split("=")[1];
- map.put(name, value);
- } else if (paramTokens.length == 3) {
- // very ugly, added for Xen tunneling url
- String name = paramTokens[0];
- String value = paramTokens[1] + "=" + paramTokens[2];
- map.put(name, value);
- } else {
- if(s_logger.isDebugEnabled())
- s_logger.debug("Invalid paramemter in URL found. param: " + param);
- }
- }
-
- // This is a ugly solution for now. We will do encryption/decryption translation
- // here to make it transparent to rest of the code.
- if(map.get("token") != null) {
- ConsoleProxyPasswordBasedEncryptor encryptor = new ConsoleProxyPasswordBasedEncryptor(
- ConsoleProxy.getEncryptorPassword());
-
- ConsoleProxyClientParam param = encryptor.decryptObject(ConsoleProxyClientParam.class, map.get("token"));
- if(param != null) {
- if(param.getClientHostAddress() != null)
- map.put("host", param.getClientHostAddress());
- if(param.getClientHostPort() != 0)
- map.put("port", String.valueOf(param.getClientHostPort()));
- if(param.getClientTag() != null)
- map.put("tag", param.getClientTag());
- if(param.getClientHostPassword() != null)
- map.put("sid", param.getClientHostPassword());
- if(param.getClientTunnelUrl() != null)
- map.put("consoleurl", param.getClientTunnelUrl());
- if(param.getClientTunnelSession() != null)
- map.put("sessionref", param.getClientTunnelSession());
- if(param.getTicket() != null)
- map.put("ticket", param.getTicket());
- }
- }
-
- return map;
- }
-}
+package com.cloud.consoleproxy;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import com.cloud.consoleproxy.util.Logger;
+
+public class ConsoleProxyHttpHandlerHelper {
+ private static final Logger s_logger = Logger.getLogger(ConsoleProxyHttpHandlerHelper.class);
+
+ public static Map getQueryMap(String query) {
+ String[] params = query.split("&");
+ Map map = new HashMap();
+ for (String param : params) {
+ String[] paramTokens = param.split("=");
+ if(paramTokens != null && paramTokens.length == 2) {
+ String name = param.split("=")[0];
+ String value = param.split("=")[1];
+ map.put(name, value);
+ } else if (paramTokens.length == 3) {
+ // very ugly, added for Xen tunneling url
+ String name = paramTokens[0];
+ String value = paramTokens[1] + "=" + paramTokens[2];
+ map.put(name, value);
+ } else {
+ if(s_logger.isDebugEnabled())
+ s_logger.debug("Invalid paramemter in URL found. param: " + param);
+ }
+ }
+
+ // This is a ugly solution for now. We will do encryption/decryption translation
+ // here to make it transparent to rest of the code.
+ if(map.get("token") != null) {
+ ConsoleProxyPasswordBasedEncryptor encryptor = new ConsoleProxyPasswordBasedEncryptor(
+ ConsoleProxy.getEncryptorPassword());
+
+ ConsoleProxyClientParam param = encryptor.decryptObject(ConsoleProxyClientParam.class, map.get("token"));
+ if(param != null) {
+ if(param.getClientHostAddress() != null)
+ map.put("host", param.getClientHostAddress());
+ if(param.getClientHostPort() != 0)
+ map.put("port", String.valueOf(param.getClientHostPort()));
+ if(param.getClientTag() != null)
+ map.put("tag", param.getClientTag());
+ if(param.getClientHostPassword() != null)
+ map.put("sid", param.getClientHostPassword());
+ if(param.getClientTunnelUrl() != null)
+ map.put("consoleurl", param.getClientTunnelUrl());
+ if(param.getClientTunnelSession() != null)
+ map.put("sessionref", param.getClientTunnelSession());
+ if(param.getTicket() != null)
+ map.put("ticket", param.getTicket());
+ }
+ }
+
+ return map;
+ }
+}
diff --git a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyLoggerFactory.java b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyLoggerFactory.java
index 701ad7a277d..ff66de3bcc4 100644
--- a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyLoggerFactory.java
+++ b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyLoggerFactory.java
@@ -14,76 +14,76 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-package com.cloud.consoleproxy;
+package com.cloud.consoleproxy;
import com.cloud.consoleproxy.util.Logger;
import com.cloud.consoleproxy.util.LoggerFactory;
-
-public class ConsoleProxyLoggerFactory implements LoggerFactory {
- public ConsoleProxyLoggerFactory() {
- }
-
- public Logger getLogger(Class> clazz) {
- return new Log4jLogger(org.apache.log4j.Logger.getLogger(clazz));
- }
-
- public static class Log4jLogger extends Logger {
- private org.apache.log4j.Logger logger;
-
- public Log4jLogger(org.apache.log4j.Logger logger) {
- this.logger = logger;
- }
-
- public boolean isTraceEnabled() {
- return logger.isTraceEnabled();
- }
-
- public boolean isDebugEnabled() {
- return logger.isDebugEnabled();
- }
-
- public boolean isInfoEnabled() {
- return logger.isInfoEnabled();
- }
-
- public void trace(Object message) {
- logger.trace(message);
- }
-
- public void trace(Object message, Throwable exception) {
- logger.trace(message, exception);
- }
-
- public void info(Object message) {
- logger.info(message);
- }
-
- public void info(Object message, Throwable exception) {
- logger.info(message, exception);
- }
-
- public void debug(Object message) {
- logger.debug(message);
- }
-
- public void debug(Object message, Throwable exception) {
- logger.debug(message, exception);
- }
-
- public void warn(Object message) {
- logger.warn(message);
- }
-
- public void warn(Object message, Throwable exception) {
- logger.warn(message, exception);
- }
-
- public void error(Object message) {
- logger.error(message);
- }
-
- public void error(Object message, Throwable exception) {
- logger.error(message, exception);
- }
- }
-}
+
+public class ConsoleProxyLoggerFactory implements LoggerFactory {
+ public ConsoleProxyLoggerFactory() {
+ }
+
+ public Logger getLogger(Class> clazz) {
+ return new Log4jLogger(org.apache.log4j.Logger.getLogger(clazz));
+ }
+
+ public static class Log4jLogger extends Logger {
+ private org.apache.log4j.Logger logger;
+
+ public Log4jLogger(org.apache.log4j.Logger logger) {
+ this.logger = logger;
+ }
+
+ public boolean isTraceEnabled() {
+ return logger.isTraceEnabled();
+ }
+
+ public boolean isDebugEnabled() {
+ return logger.isDebugEnabled();
+ }
+
+ public boolean isInfoEnabled() {
+ return logger.isInfoEnabled();
+ }
+
+ public void trace(Object message) {
+ logger.trace(message);
+ }
+
+ public void trace(Object message, Throwable exception) {
+ logger.trace(message, exception);
+ }
+
+ public void info(Object message) {
+ logger.info(message);
+ }
+
+ public void info(Object message, Throwable exception) {
+ logger.info(message, exception);
+ }
+
+ public void debug(Object message) {
+ logger.debug(message);
+ }
+
+ public void debug(Object message, Throwable exception) {
+ logger.debug(message, exception);
+ }
+
+ public void warn(Object message) {
+ logger.warn(message);
+ }
+
+ public void warn(Object message, Throwable exception) {
+ logger.warn(message, exception);
+ }
+
+ public void error(Object message) {
+ logger.error(message);
+ }
+
+ public void error(Object message, Throwable exception) {
+ logger.error(message, exception);
+ }
+ }
+}
diff --git a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyMonitor.java b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyMonitor.java
index be5df6efa59..030b2f452eb 100644
--- a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyMonitor.java
+++ b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyMonitor.java
@@ -34,120 +34,120 @@ import com.cloud.consoleproxy.util.Logger;
// itself and the shell script will re-launch console proxy
//
public class ConsoleProxyMonitor {
- private static final Logger s_logger = Logger.getLogger(ConsoleProxyMonitor.class);
-
- private String[] _argv;
- private Map _argMap = new HashMap();
-
- private volatile Process _process;
- private boolean _quit = false;
-
- public ConsoleProxyMonitor(String[] argv) {
- _argv = argv;
-
- for(String arg : _argv) {
- String[] tokens = arg.split("=");
- if(tokens.length == 2) {
- s_logger.info("Add argument " + tokens[0] + "=" + tokens[1] + " to the argument map");
+ private static final Logger s_logger = Logger.getLogger(ConsoleProxyMonitor.class);
+
+ private String[] _argv;
+ private Map _argMap = new HashMap();
+
+ private volatile Process _process;
+ private boolean _quit = false;
+
+ public ConsoleProxyMonitor(String[] argv) {
+ _argv = argv;
+
+ for(String arg : _argv) {
+ String[] tokens = arg.split("=");
+ if(tokens.length == 2) {
+ s_logger.info("Add argument " + tokens[0] + "=" + tokens[1] + " to the argument map");
- _argMap.put(tokens[0].trim(), tokens[1].trim());
- } else {
- s_logger.warn("unrecognized argument, skip adding it to argument map");
- }
- }
- }
-
- private void run() {
- Runtime.getRuntime().addShutdownHook(new Thread() {
- @Override
- public void run() {
- _quit = true;
- onShutdown();
- }
- });
-
- while(!_quit) {
- String cmdLine = getLaunchCommandLine();
-
- s_logger.info("Launch console proxy process with command line: " + cmdLine);
-
- try {
- _process = Runtime.getRuntime().exec(cmdLine);
- } catch (IOException e) {
- s_logger.error("Unexpected exception ", e);
- System.exit(1);
- }
-
- boolean waitSucceeded = false;
- int exitCode = 0;
- while(!waitSucceeded) {
- try {
- exitCode = _process.waitFor();
- waitSucceeded = true;
-
- if(s_logger.isInfoEnabled())
- s_logger.info("Console proxy process exits with code: " + exitCode);
- } catch (InterruptedException e) {
- if(s_logger.isInfoEnabled())
- s_logger.info("InterruptedException while waiting for termination of console proxy, will retry");
- }
- }
- }
- }
-
- private String getLaunchCommandLine() {
- StringBuffer sb = new StringBuffer("java ");
- String jvmOptions = _argMap.get("jvmoptions");
-
- if(jvmOptions != null)
- sb.append(jvmOptions);
-
- for(Map.Entry entry : _argMap.entrySet()) {
- if(!"jvmoptions".equalsIgnoreCase(entry.getKey()))
- sb.append(" ").append(entry.getKey()).append("=").append(entry.getValue());
- }
-
- return sb.toString();
- }
-
- private void onShutdown() {
- if(_process != null) {
- if(s_logger.isInfoEnabled())
- s_logger.info("Console proxy monitor shuts dwon, terminate console proxy process");
- _process.destroy();
- }
- }
+ _argMap.put(tokens[0].trim(), tokens[1].trim());
+ } else {
+ s_logger.warn("unrecognized argument, skip adding it to argument map");
+ }
+ }
+ }
+
+ private void run() {
+ Runtime.getRuntime().addShutdownHook(new Thread() {
+ @Override
+ public void run() {
+ _quit = true;
+ onShutdown();
+ }
+ });
+
+ while(!_quit) {
+ String cmdLine = getLaunchCommandLine();
+
+ s_logger.info("Launch console proxy process with command line: " + cmdLine);
+
+ try {
+ _process = Runtime.getRuntime().exec(cmdLine);
+ } catch (IOException e) {
+ s_logger.error("Unexpected exception ", e);
+ System.exit(1);
+ }
+
+ boolean waitSucceeded = false;
+ int exitCode = 0;
+ while(!waitSucceeded) {
+ try {
+ exitCode = _process.waitFor();
+ waitSucceeded = true;
+
+ if(s_logger.isInfoEnabled())
+ s_logger.info("Console proxy process exits with code: " + exitCode);
+ } catch (InterruptedException e) {
+ if(s_logger.isInfoEnabled())
+ s_logger.info("InterruptedException while waiting for termination of console proxy, will retry");
+ }
+ }
+ }
+ }
+
+ private String getLaunchCommandLine() {
+ StringBuffer sb = new StringBuffer("java ");
+ String jvmOptions = _argMap.get("jvmoptions");
+
+ if(jvmOptions != null)
+ sb.append(jvmOptions);
+
+ for(Map.Entry entry : _argMap.entrySet()) {
+ if(!"jvmoptions".equalsIgnoreCase(entry.getKey()))
+ sb.append(" ").append(entry.getKey()).append("=").append(entry.getValue());
+ }
+
+ return sb.toString();
+ }
+
+ private void onShutdown() {
+ if(_process != null) {
+ if(s_logger.isInfoEnabled())
+ s_logger.info("Console proxy monitor shuts dwon, terminate console proxy process");
+ _process.destroy();
+ }
+ }
- private static void configLog4j() {
- URL configUrl = System.class.getResource("/conf/log4j-cloud.xml");
- if(configUrl == null)
- configUrl = ClassLoader.getSystemResource("log4j-cloud.xml");
-
- if(configUrl == null)
- configUrl = ClassLoader.getSystemResource("conf/log4j-cloud.xml");
-
- if(configUrl != null) {
- try {
- System.out.println("Configure log4j using " + configUrl.toURI().toString());
- } catch (URISyntaxException e1) {
- e1.printStackTrace();
- }
+ private static void configLog4j() {
+ URL configUrl = System.class.getResource("/conf/log4j-cloud.xml");
+ if(configUrl == null)
+ configUrl = ClassLoader.getSystemResource("log4j-cloud.xml");
+
+ if(configUrl == null)
+ configUrl = ClassLoader.getSystemResource("conf/log4j-cloud.xml");
+
+ if(configUrl != null) {
+ try {
+ System.out.println("Configure log4j using " + configUrl.toURI().toString());
+ } catch (URISyntaxException e1) {
+ e1.printStackTrace();
+ }
- try {
- File file = new File(configUrl.toURI());
-
- System.out.println("Log4j configuration from : " + file.getAbsolutePath());
- DOMConfigurator.configureAndWatch(file.getAbsolutePath(), 10000);
- } catch (URISyntaxException e) {
- System.out.println("Unable to convert log4j configuration Url to URI");
- }
- } else {
- System.out.println("Configure log4j with default properties");
- }
- }
-
- public static void main(String[] argv) {
- configLog4j();
- (new ConsoleProxyMonitor(argv)).run();
- }
+ try {
+ File file = new File(configUrl.toURI());
+
+ System.out.println("Log4j configuration from : " + file.getAbsolutePath());
+ DOMConfigurator.configureAndWatch(file.getAbsolutePath(), 10000);
+ } catch (URISyntaxException e) {
+ System.out.println("Unable to convert log4j configuration Url to URI");
+ }
+ } else {
+ System.out.println("Configure log4j with default properties");
+ }
+ }
+
+ public static void main(String[] argv) {
+ configLog4j();
+ (new ConsoleProxyMonitor(argv)).run();
+ }
}
diff --git a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyResourceHandler.java b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyResourceHandler.java
index f9dc21e1575..7d160472e8a 100644
--- a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyResourceHandler.java
+++ b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyResourceHandler.java
@@ -14,168 +14,168 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-package com.cloud.consoleproxy;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Date;
-import java.util.HashMap;
-import java.util.Map;
-
+package com.cloud.consoleproxy;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.Map;
+
import com.cloud.consoleproxy.util.Logger;
-import com.sun.net.httpserver.Headers;
-import com.sun.net.httpserver.HttpExchange;
-import com.sun.net.httpserver.HttpHandler;
-
-public class ConsoleProxyResourceHandler implements HttpHandler {
- private static final Logger s_logger = Logger.getLogger(ConsoleProxyResourceHandler.class);
-
- static Map s_mimeTypes;
- static {
- s_mimeTypes = new HashMap();
- s_mimeTypes.put("jar", "application/java-archive");
- s_mimeTypes.put("js", "text/javascript");
- s_mimeTypes.put("css", "text/css");
- s_mimeTypes.put("jpg", "image/jpeg");
- s_mimeTypes.put("html", "text/html");
- s_mimeTypes.put("htm", "text/html");
- s_mimeTypes.put("log", "text/plain");
- }
-
- static Map s_validResourceFolders;
- static {
- s_validResourceFolders = new HashMap();
- s_validResourceFolders.put("applet", "");
- s_validResourceFolders.put("logs", "");
- s_validResourceFolders.put("images", "");
- s_validResourceFolders.put("js", "");
- s_validResourceFolders.put("css", "");
- s_validResourceFolders.put("html", "");
- }
-
- public ConsoleProxyResourceHandler() {
- }
-
- public void handle(HttpExchange t) throws IOException {
- try {
- if(s_logger.isDebugEnabled())
- s_logger.debug("Resource Handler " + t.getRequestURI());
-
- long startTick = System.currentTimeMillis();
-
- doHandle(t);
-
- if(s_logger.isDebugEnabled())
- s_logger.debug(t.getRequestURI() + " Process time " + (System.currentTimeMillis() - startTick) + " ms");
- } catch (IOException e) {
- throw e;
- } catch(Throwable e) {
- s_logger.error("Unexpected exception, ", e);
- t.sendResponseHeaders(500, -1); // server error
- } finally {
- t.close();
- }
- }
-
- @SuppressWarnings("deprecation")
- private void doHandle(HttpExchange t) throws Exception {
- String path = t.getRequestURI().getPath();
-
- if(s_logger.isInfoEnabled())
- s_logger.info("Get resource request for " + path);
-
- int i = path.indexOf("/", 1);
- String filepath = path.substring(i + 1);
- i = path.lastIndexOf(".");
- String extension = (i == -1) ? "" : path.substring(i + 1);
- String contentType = getContentType(extension);
-
- if(!validatePath(filepath)) {
- if(s_logger.isInfoEnabled())
- s_logger.info("Resource access is forbidden, uri: " + path);
-
- t.sendResponseHeaders(403, -1); // forbidden
- return;
- }
-
- File f = new File ("./" + filepath);
- if(f.exists()) {
- long lastModified = f.lastModified();
- String ifModifiedSince = t.getRequestHeaders().getFirst("If-Modified-Since");
- if (ifModifiedSince != null) {
- long d = Date.parse(ifModifiedSince);
- if (d + 1000 >= lastModified) {
- Headers hds = t.getResponseHeaders();
- hds.set("Content-Type", contentType);
- t.sendResponseHeaders(304, -1);
-
- if(s_logger.isInfoEnabled())
- s_logger.info("Sent 304 file has not been " +
- "modified since " + ifModifiedSince);
- return;
- }
- }
-
- long length = f.length();
- Headers hds = t.getResponseHeaders();
- hds.set("Content-Type", contentType);
- hds.set("Last-Modified", new Date(lastModified).toGMTString());
- t.sendResponseHeaders(200, length);
- responseFileContent(t, f);
-
- if(s_logger.isInfoEnabled())
- s_logger.info("Sent file " + path + " with content type " + contentType);
- } else {
- if(s_logger.isInfoEnabled())
- s_logger.info("file does not exist" + path);
- t.sendResponseHeaders(404, -1);
- }
- }
-
- private static String getContentType(String extension) {
- String key = extension.toLowerCase();
- if(s_mimeTypes.containsKey(key)) {
- return s_mimeTypes.get(key);
- }
- return "application/octet-stream";
- }
-
- private static void responseFileContent(HttpExchange t, File f) throws Exception {
- OutputStream os = t.getResponseBody();
- FileInputStream fis = new FileInputStream(f);
- while (true) {
- byte[] b = new byte[8192];
- int n = fis.read(b);
- if (n < 0) {
- break;
- }
- os.write(b, 0, n);
- }
- fis.close();
- os.close();
- }
-
- private static boolean validatePath(String path) {
- int i = path.indexOf("/");
- if(i == -1) {
- if(s_logger.isInfoEnabled())
- s_logger.info("Invalid resource path: can not start at resource root");
- return false;
- }
-
- if(path.contains("..")) {
- if(s_logger.isInfoEnabled())
- s_logger.info("Invalid resource path: contains relative up-level navigation");
-
- return false;
- }
-
- return isValidResourceFolder(path.substring(0, i));
- }
-
- private static boolean isValidResourceFolder(String name) {
- return s_validResourceFolders.containsKey(name);
- }
-}
+import com.sun.net.httpserver.Headers;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
+
+public class ConsoleProxyResourceHandler implements HttpHandler {
+ private static final Logger s_logger = Logger.getLogger(ConsoleProxyResourceHandler.class);
+
+ static Map s_mimeTypes;
+ static {
+ s_mimeTypes = new HashMap();
+ s_mimeTypes.put("jar", "application/java-archive");
+ s_mimeTypes.put("js", "text/javascript");
+ s_mimeTypes.put("css", "text/css");
+ s_mimeTypes.put("jpg", "image/jpeg");
+ s_mimeTypes.put("html", "text/html");
+ s_mimeTypes.put("htm", "text/html");
+ s_mimeTypes.put("log", "text/plain");
+ }
+
+ static Map s_validResourceFolders;
+ static {
+ s_validResourceFolders = new HashMap();
+ s_validResourceFolders.put("applet", "");
+ s_validResourceFolders.put("logs", "");
+ s_validResourceFolders.put("images", "");
+ s_validResourceFolders.put("js", "");
+ s_validResourceFolders.put("css", "");
+ s_validResourceFolders.put("html", "");
+ }
+
+ public ConsoleProxyResourceHandler() {
+ }
+
+ public void handle(HttpExchange t) throws IOException {
+ try {
+ if(s_logger.isDebugEnabled())
+ s_logger.debug("Resource Handler " + t.getRequestURI());
+
+ long startTick = System.currentTimeMillis();
+
+ doHandle(t);
+
+ if(s_logger.isDebugEnabled())
+ s_logger.debug(t.getRequestURI() + " Process time " + (System.currentTimeMillis() - startTick) + " ms");
+ } catch (IOException e) {
+ throw e;
+ } catch(Throwable e) {
+ s_logger.error("Unexpected exception, ", e);
+ t.sendResponseHeaders(500, -1); // server error
+ } finally {
+ t.close();
+ }
+ }
+
+ @SuppressWarnings("deprecation")
+ private void doHandle(HttpExchange t) throws Exception {
+ String path = t.getRequestURI().getPath();
+
+ if(s_logger.isInfoEnabled())
+ s_logger.info("Get resource request for " + path);
+
+ int i = path.indexOf("/", 1);
+ String filepath = path.substring(i + 1);
+ i = path.lastIndexOf(".");
+ String extension = (i == -1) ? "" : path.substring(i + 1);
+ String contentType = getContentType(extension);
+
+ if(!validatePath(filepath)) {
+ if(s_logger.isInfoEnabled())
+ s_logger.info("Resource access is forbidden, uri: " + path);
+
+ t.sendResponseHeaders(403, -1); // forbidden
+ return;
+ }
+
+ File f = new File ("./" + filepath);
+ if(f.exists()) {
+ long lastModified = f.lastModified();
+ String ifModifiedSince = t.getRequestHeaders().getFirst("If-Modified-Since");
+ if (ifModifiedSince != null) {
+ long d = Date.parse(ifModifiedSince);
+ if (d + 1000 >= lastModified) {
+ Headers hds = t.getResponseHeaders();
+ hds.set("Content-Type", contentType);
+ t.sendResponseHeaders(304, -1);
+
+ if(s_logger.isInfoEnabled())
+ s_logger.info("Sent 304 file has not been " +
+ "modified since " + ifModifiedSince);
+ return;
+ }
+ }
+
+ long length = f.length();
+ Headers hds = t.getResponseHeaders();
+ hds.set("Content-Type", contentType);
+ hds.set("Last-Modified", new Date(lastModified).toGMTString());
+ t.sendResponseHeaders(200, length);
+ responseFileContent(t, f);
+
+ if(s_logger.isInfoEnabled())
+ s_logger.info("Sent file " + path + " with content type " + contentType);
+ } else {
+ if(s_logger.isInfoEnabled())
+ s_logger.info("file does not exist" + path);
+ t.sendResponseHeaders(404, -1);
+ }
+ }
+
+ private static String getContentType(String extension) {
+ String key = extension.toLowerCase();
+ if(s_mimeTypes.containsKey(key)) {
+ return s_mimeTypes.get(key);
+ }
+ return "application/octet-stream";
+ }
+
+ private static void responseFileContent(HttpExchange t, File f) throws Exception {
+ OutputStream os = t.getResponseBody();
+ FileInputStream fis = new FileInputStream(f);
+ while (true) {
+ byte[] b = new byte[8192];
+ int n = fis.read(b);
+ if (n < 0) {
+ break;
+ }
+ os.write(b, 0, n);
+ }
+ fis.close();
+ os.close();
+ }
+
+ private static boolean validatePath(String path) {
+ int i = path.indexOf("/");
+ if(i == -1) {
+ if(s_logger.isInfoEnabled())
+ s_logger.info("Invalid resource path: can not start at resource root");
+ return false;
+ }
+
+ if(path.contains("..")) {
+ if(s_logger.isInfoEnabled())
+ s_logger.info("Invalid resource path: contains relative up-level navigation");
+
+ return false;
+ }
+
+ return isValidResourceFolder(path.substring(0, i));
+ }
+
+ private static boolean isValidResourceFolder(String name) {
+ return s_validResourceFolders.containsKey(name);
+ }
+}
diff --git a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxySecureServerFactoryImpl.java b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxySecureServerFactoryImpl.java
index 42d069f9331..ee0ee13fa92 100644
--- a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxySecureServerFactoryImpl.java
+++ b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxySecureServerFactoryImpl.java
@@ -14,8 +14,8 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-package com.cloud.consoleproxy;
-
+package com.cloud.consoleproxy;
+
import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
@@ -35,111 +35,111 @@ import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsParameters;
import com.sun.net.httpserver.HttpsServer;
-
-public class ConsoleProxySecureServerFactoryImpl implements ConsoleProxyServerFactory {
- private static final Logger s_logger = Logger.getLogger(ConsoleProxySecureServerFactoryImpl.class);
-
- private SSLContext sslContext = null;
-
- public ConsoleProxySecureServerFactoryImpl() {
- }
-
- @Override
- public void init(byte[] ksBits, String ksPassword) {
- s_logger.info("Start initializing SSL");
- if(ksBits == null) {
- try {
- s_logger.info("Initializing SSL from built-in default certificate");
-
- char[] passphrase = "vmops.com".toCharArray();
- KeyStore ks = KeyStore.getInstance("JKS");
-
- ks.load(new FileInputStream("certs/realhostip.keystore"), passphrase);
- // ks.load(ConsoleProxy.class.getResourceAsStream("/realhostip.keystore"), passphrase);
-
- s_logger.info("SSL certificate loaded");
-
- KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
- kmf.init(ks, passphrase);
- s_logger.info("Key manager factory is initialized");
+public class ConsoleProxySecureServerFactoryImpl implements ConsoleProxyServerFactory {
+ private static final Logger s_logger = Logger.getLogger(ConsoleProxySecureServerFactoryImpl.class);
+
+ private SSLContext sslContext = null;
+
+ public ConsoleProxySecureServerFactoryImpl() {
+ }
+
+ @Override
+ public void init(byte[] ksBits, String ksPassword) {
+ s_logger.info("Start initializing SSL");
- TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
- tmf.init(ks);
- s_logger.info("Trust manager factory is initialized");
+ if(ksBits == null) {
+ try {
+ s_logger.info("Initializing SSL from built-in default certificate");
+
+ char[] passphrase = "vmops.com".toCharArray();
+ KeyStore ks = KeyStore.getInstance("JKS");
+
+ ks.load(new FileInputStream("certs/realhostip.keystore"), passphrase);
+ // ks.load(ConsoleProxy.class.getResourceAsStream("/realhostip.keystore"), passphrase);
+
+ s_logger.info("SSL certificate loaded");
+
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+ kmf.init(ks, passphrase);
+ s_logger.info("Key manager factory is initialized");
- sslContext = SSLContext.getInstance("TLS");
- sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
- s_logger.info("SSL context is initialized");
- } catch (Exception ioe) {
- s_logger.error(ioe.toString(), ioe);
- }
-
- } else {
- char[] passphrase = ksPassword != null ? ksPassword.toCharArray() : null;
- try {
- s_logger.info("Initializing SSL from passed-in certificate");
-
- KeyStore ks = KeyStore.getInstance("JKS");
- ks.load(new ByteArrayInputStream(ksBits), passphrase);
-
- KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
- kmf.init(ks, passphrase);
- s_logger.info("Key manager factory is initialized");
-
- TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
- tmf.init(ks);
- s_logger.info("Trust manager factory is initialized");
-
- sslContext = SSLContext.getInstance("TLS");
- sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
- s_logger.info("SSL context is initialized");
- } catch(Exception e) {
- s_logger.error("Unable to init factory due to exception ", e);
- }
- }
-
- }
-
- public HttpServer createHttpServerInstance(int port) throws IOException {
- try {
- HttpsServer server = HttpsServer.create(new InetSocketAddress(port), 5);
- server.setHttpsConfigurator (new HttpsConfigurator(sslContext) {
- @Override
- public void configure (HttpsParameters params) {
-
- // get the remote address if needed
- InetSocketAddress remote = params.getClientAddress();
- SSLContext c = getSSLContext();
-
- // get the default parameters
- SSLParameters sslparams = c.getDefaultSSLParameters();
-
- params.setSSLParameters(sslparams);
- // statement above could throw IAE if any params invalid.
- // eg. if app has a UI and parameters supplied by a user.
- }
- });
-
- s_logger.info("create HTTPS server instance on port: " + port);
- return server;
- } catch (Exception ioe) {
- s_logger.error(ioe.toString(), ioe);
- }
- return null;
- }
-
- public SSLServerSocket createSSLServerSocket(int port) throws IOException {
- try {
- SSLServerSocket srvSock = null;
- SSLServerSocketFactory ssf = sslContext.getServerSocketFactory();
- srvSock = (SSLServerSocket) ssf.createServerSocket(port);
-
- s_logger.info("create SSL server socket on port: " + port);
- return srvSock;
- } catch (Exception ioe) {
- s_logger.error(ioe.toString(), ioe);
- }
- return null;
- }
-}
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
+ tmf.init(ks);
+ s_logger.info("Trust manager factory is initialized");
+
+ sslContext = SSLContext.getInstance("TLS");
+ sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+ s_logger.info("SSL context is initialized");
+ } catch (Exception ioe) {
+ s_logger.error(ioe.toString(), ioe);
+ }
+
+ } else {
+ char[] passphrase = ksPassword != null ? ksPassword.toCharArray() : null;
+ try {
+ s_logger.info("Initializing SSL from passed-in certificate");
+
+ KeyStore ks = KeyStore.getInstance("JKS");
+ ks.load(new ByteArrayInputStream(ksBits), passphrase);
+
+ KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
+ kmf.init(ks, passphrase);
+ s_logger.info("Key manager factory is initialized");
+
+ TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
+ tmf.init(ks);
+ s_logger.info("Trust manager factory is initialized");
+
+ sslContext = SSLContext.getInstance("TLS");
+ sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
+ s_logger.info("SSL context is initialized");
+ } catch(Exception e) {
+ s_logger.error("Unable to init factory due to exception ", e);
+ }
+ }
+
+ }
+
+ public HttpServer createHttpServerInstance(int port) throws IOException {
+ try {
+ HttpsServer server = HttpsServer.create(new InetSocketAddress(port), 5);
+ server.setHttpsConfigurator (new HttpsConfigurator(sslContext) {
+ @Override
+ public void configure (HttpsParameters params) {
+
+ // get the remote address if needed
+ InetSocketAddress remote = params.getClientAddress();
+ SSLContext c = getSSLContext();
+
+ // get the default parameters
+ SSLParameters sslparams = c.getDefaultSSLParameters();
+
+ params.setSSLParameters(sslparams);
+ // statement above could throw IAE if any params invalid.
+ // eg. if app has a UI and parameters supplied by a user.
+ }
+ });
+
+ s_logger.info("create HTTPS server instance on port: " + port);
+ return server;
+ } catch (Exception ioe) {
+ s_logger.error(ioe.toString(), ioe);
+ }
+ return null;
+ }
+
+ public SSLServerSocket createSSLServerSocket(int port) throws IOException {
+ try {
+ SSLServerSocket srvSock = null;
+ SSLServerSocketFactory ssf = sslContext.getServerSocketFactory();
+ srvSock = (SSLServerSocket) ssf.createServerSocket(port);
+
+ s_logger.info("create SSL server socket on port: " + port);
+ return srvSock;
+ } catch (Exception ioe) {
+ s_logger.error(ioe.toString(), ioe);
+ }
+ return null;
+ }
+}
diff --git a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyServerFactory.java b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyServerFactory.java
index 9d65c00d096..7e0e5c77bf4 100644
--- a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyServerFactory.java
+++ b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyServerFactory.java
@@ -14,16 +14,16 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-package com.cloud.consoleproxy;
-
+package com.cloud.consoleproxy;
+
import java.io.IOException;
import javax.net.ssl.SSLServerSocket;
import com.sun.net.httpserver.HttpServer;
-
+
public interface ConsoleProxyServerFactory {
- void init(byte[] ksBits, String ksPassword);
- HttpServer createHttpServerInstance(int port) throws IOException;
- SSLServerSocket createSSLServerSocket(int port) throws IOException;
-}
+ void init(byte[] ksBits, String ksPassword);
+ HttpServer createHttpServerInstance(int port) throws IOException;
+ SSLServerSocket createSSLServerSocket(int port) throws IOException;
+}
diff --git a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyThumbnailHandler.java b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyThumbnailHandler.java
index 82d45b77e74..6d34d3b9162 100644
--- a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyThumbnailHandler.java
+++ b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyThumbnailHandler.java
@@ -14,199 +14,199 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-package com.cloud.consoleproxy;
-
-import java.awt.Color;
-import java.awt.Font;
-import java.awt.FontMetrics;
-import java.awt.Graphics2D;
-import java.awt.Image;
-import java.awt.image.BufferedImage;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.HashMap;
-import java.util.Map;
-
+package com.cloud.consoleproxy;
+
+import java.awt.Color;
+import java.awt.Font;
+import java.awt.FontMetrics;
+import java.awt.Graphics2D;
+import java.awt.Image;
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.HashMap;
+import java.util.Map;
+
import com.cloud.consoleproxy.util.Logger;
-import com.sun.net.httpserver.Headers;
-import com.sun.net.httpserver.HttpExchange;
-import com.sun.net.httpserver.HttpHandler;
-
-public class ConsoleProxyThumbnailHandler implements HttpHandler {
- private static final Logger s_logger = Logger.getLogger(ConsoleProxyThumbnailHandler.class);
-
- public ConsoleProxyThumbnailHandler() {
- }
-
- public void handle(HttpExchange t) throws IOException {
- try {
- Thread.currentThread().setName("JPG Thread " +
- Thread.currentThread().getId() + " " + t.getRemoteAddress());
-
- if(s_logger.isDebugEnabled())
- s_logger.debug("ScreenHandler " + t.getRequestURI());
-
- long startTick = System.currentTimeMillis();
- doHandle(t);
-
- if(s_logger.isDebugEnabled())
- s_logger.debug(t.getRequestURI() + "Process time " + (System.currentTimeMillis() - startTick) + " ms");
- } catch (IllegalArgumentException e) {
- String response = "Bad query string";
- s_logger.error(response + ", request URI : " + t.getRequestURI());
- t.sendResponseHeaders(200, response.length());
- OutputStream os = t.getResponseBody();
- os.write(response.getBytes());
- os.close();
- } catch(OutOfMemoryError e) {
- s_logger.error("Unrecoverable OutOfMemory Error, exit and let it be re-launched");
- System.exit(1);
- } catch (Throwable e) {
- s_logger.error("Unexpected exception while handing thumbnail request, ", e);
-
- String queries = t.getRequestURI().getQuery();
- Map queryMap = getQueryMap(queries);
- int width = 0;
- int height = 0;
- String ws = queryMap.get("w");
- String hs = queryMap.get("h");
- try {
- width = Integer.parseInt(ws);
- height = Integer.parseInt(hs);
- } catch (NumberFormatException ex) {
- }
- width = Math.min(width, 800);
- height = Math.min(height, 600);
-
- BufferedImage img = generateTextImage(width, height, "Cannot Connect");
- ByteArrayOutputStream bos = new ByteArrayOutputStream(8196);
- javax.imageio.ImageIO.write(img, "jpg", bos);
- byte[] bs = bos.toByteArray();
- Headers hds = t.getResponseHeaders();
- hds.set("Content-Type", "image/jpeg");
- hds.set("Cache-Control", "no-cache");
- hds.set("Cache-Control", "no-store");
- t.sendResponseHeaders(200, bs.length);
- OutputStream os = t.getResponseBody();
- os.write(bs);
- os.close();
- s_logger.error("Cannot get console, sent error JPG response for " + t.getRequestURI());
- return;
- } finally {
- t.close();
- }
- }
-
- private void doHandle(HttpExchange t) throws Exception, IllegalArgumentException {
- String queries = t.getRequestURI().getQuery();
- Map queryMap = getQueryMap(queries);
- int width = 0;
- int height = 0;
- int port = 0;
- String ws = queryMap.get("w");
- String hs = queryMap.get("h");
- String host = queryMap.get("host");
- String portStr = queryMap.get("port");
- String sid = queryMap.get("sid");
- String tag = queryMap.get("tag");
- String ticket = queryMap.get("ticket");
- String console_url = queryMap.get("consoleurl");
- String console_host_session = queryMap.get("sessionref");
+import com.sun.net.httpserver.Headers;
+import com.sun.net.httpserver.HttpExchange;
+import com.sun.net.httpserver.HttpHandler;
- if(tag == null)
- tag = "";
-
- if (ws == null || hs == null || host == null || portStr == null || sid == null ) {
- throw new IllegalArgumentException();
- }
- try {
- width = Integer.parseInt(ws);
- height = Integer.parseInt(hs);
- port = Integer.parseInt(portStr);
- } catch (NumberFormatException e) {
- throw new IllegalArgumentException(e);
- }
+public class ConsoleProxyThumbnailHandler implements HttpHandler {
+ private static final Logger s_logger = Logger.getLogger(ConsoleProxyThumbnailHandler.class);
+
+ public ConsoleProxyThumbnailHandler() {
+ }
- ConsoleProxyClientParam param = new ConsoleProxyClientParam();
- param.setClientHostAddress(host);
- param.setClientHostPort(port);
- param.setClientHostPassword(sid);
- param.setClientTag(tag);
- param.setTicket(ticket);
- param.setClientTunnelUrl(console_url);
- param.setClientTunnelSession(console_host_session);
-
- ConsoleProxyClient viewer = ConsoleProxy.getVncViewer(param);
-
- if (!viewer.isHostConnected()) {
- // use generated image instead of static
- BufferedImage img = generateTextImage(width, height, "Connecting");
- ByteArrayOutputStream bos = new ByteArrayOutputStream(8196);
- javax.imageio.ImageIO.write(img, "jpg", bos);
- byte[] bs = bos.toByteArray();
- Headers hds = t.getResponseHeaders();
- hds.set("Content-Type", "image/jpeg");
- hds.set("Cache-Control", "no-cache");
- hds.set("Cache-Control", "no-store");
- t.sendResponseHeaders(200, bs.length);
- OutputStream os = t.getResponseBody();
- os.write(bs);
- os.close();
-
- if(s_logger.isInfoEnabled())
- s_logger.info("Console not ready, sent dummy JPG response");
- return;
- }
-
- {
- Image scaledImage = viewer.getClientScaledImage(width, height);
- BufferedImage bufferedImage = new BufferedImage(width, height,
- BufferedImage.TYPE_3BYTE_BGR);
- Graphics2D bufImageGraphics = bufferedImage.createGraphics();
- bufImageGraphics.drawImage(scaledImage, 0, 0, null);
- ByteArrayOutputStream bos = new ByteArrayOutputStream(8196);
- javax.imageio.ImageIO.write(bufferedImage, "jpg", bos);
- byte[] bs = bos.toByteArray();
- Headers hds = t.getResponseHeaders();
- hds.set("Content-Type", "image/jpeg");
- hds.set("Cache-Control", "no-cache");
- hds.set("Cache-Control", "no-store");
- t.sendResponseHeaders(200, bs.length);
- OutputStream os = t.getResponseBody();
- os.write(bs);
- os.close();
- }
- }
-
- public static BufferedImage generateTextImage(int w, int h, String text) {
- BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR);
- Graphics2D g = img.createGraphics();
- g.setColor(Color.BLACK);
- g.fillRect(0, 0, w, h);
- g.setColor(Color.WHITE);
- try {
- g.setFont(new Font(null, Font.PLAIN, 12));
- FontMetrics fm = g.getFontMetrics();
- int textWidth = fm.stringWidth(text);
- int startx = (w-textWidth) / 2;
- if(startx < 0)
- startx = 0;
- g.drawString(text, startx, h/2);
- } catch (Throwable e) {
- s_logger.warn("Problem in generating text to thumnail image, return blank image");
- }
- return img;
- }
-
- public static Map getQueryMap(String query) {
- String[] params = query.split("&");
- Map map = new HashMap();
- for (String param : params) {
- String name = param.split("=")[0];
- String value = param.split("=")[1];
- map.put(name, value);
- }
- return map;
- }
-}
+ public void handle(HttpExchange t) throws IOException {
+ try {
+ Thread.currentThread().setName("JPG Thread " +
+ Thread.currentThread().getId() + " " + t.getRemoteAddress());
+
+ if(s_logger.isDebugEnabled())
+ s_logger.debug("ScreenHandler " + t.getRequestURI());
+
+ long startTick = System.currentTimeMillis();
+ doHandle(t);
+
+ if(s_logger.isDebugEnabled())
+ s_logger.debug(t.getRequestURI() + "Process time " + (System.currentTimeMillis() - startTick) + " ms");
+ } catch (IllegalArgumentException e) {
+ String response = "Bad query string";
+ s_logger.error(response + ", request URI : " + t.getRequestURI());
+ t.sendResponseHeaders(200, response.length());
+ OutputStream os = t.getResponseBody();
+ os.write(response.getBytes());
+ os.close();
+ } catch(OutOfMemoryError e) {
+ s_logger.error("Unrecoverable OutOfMemory Error, exit and let it be re-launched");
+ System.exit(1);
+ } catch (Throwable e) {
+ s_logger.error("Unexpected exception while handing thumbnail request, ", e);
+
+ String queries = t.getRequestURI().getQuery();
+ Map queryMap = getQueryMap(queries);
+ int width = 0;
+ int height = 0;
+ String ws = queryMap.get("w");
+ String hs = queryMap.get("h");
+ try {
+ width = Integer.parseInt(ws);
+ height = Integer.parseInt(hs);
+ } catch (NumberFormatException ex) {
+ }
+ width = Math.min(width, 800);
+ height = Math.min(height, 600);
+
+ BufferedImage img = generateTextImage(width, height, "Cannot Connect");
+ ByteArrayOutputStream bos = new ByteArrayOutputStream(8196);
+ javax.imageio.ImageIO.write(img, "jpg", bos);
+ byte[] bs = bos.toByteArray();
+ Headers hds = t.getResponseHeaders();
+ hds.set("Content-Type", "image/jpeg");
+ hds.set("Cache-Control", "no-cache");
+ hds.set("Cache-Control", "no-store");
+ t.sendResponseHeaders(200, bs.length);
+ OutputStream os = t.getResponseBody();
+ os.write(bs);
+ os.close();
+ s_logger.error("Cannot get console, sent error JPG response for " + t.getRequestURI());
+ return;
+ } finally {
+ t.close();
+ }
+ }
+
+ private void doHandle(HttpExchange t) throws Exception, IllegalArgumentException {
+ String queries = t.getRequestURI().getQuery();
+ Map queryMap = getQueryMap(queries);
+ int width = 0;
+ int height = 0;
+ int port = 0;
+ String ws = queryMap.get("w");
+ String hs = queryMap.get("h");
+ String host = queryMap.get("host");
+ String portStr = queryMap.get("port");
+ String sid = queryMap.get("sid");
+ String tag = queryMap.get("tag");
+ String ticket = queryMap.get("ticket");
+ String console_url = queryMap.get("consoleurl");
+ String console_host_session = queryMap.get("sessionref");
+
+ if(tag == null)
+ tag = "";
+
+ if (ws == null || hs == null || host == null || portStr == null || sid == null ) {
+ throw new IllegalArgumentException();
+ }
+ try {
+ width = Integer.parseInt(ws);
+ height = Integer.parseInt(hs);
+ port = Integer.parseInt(portStr);
+ } catch (NumberFormatException e) {
+ throw new IllegalArgumentException(e);
+ }
+
+ ConsoleProxyClientParam param = new ConsoleProxyClientParam();
+ param.setClientHostAddress(host);
+ param.setClientHostPort(port);
+ param.setClientHostPassword(sid);
+ param.setClientTag(tag);
+ param.setTicket(ticket);
+ param.setClientTunnelUrl(console_url);
+ param.setClientTunnelSession(console_host_session);
+
+ ConsoleProxyClient viewer = ConsoleProxy.getVncViewer(param);
+
+ if (!viewer.isHostConnected()) {
+ // use generated image instead of static
+ BufferedImage img = generateTextImage(width, height, "Connecting");
+ ByteArrayOutputStream bos = new ByteArrayOutputStream(8196);
+ javax.imageio.ImageIO.write(img, "jpg", bos);
+ byte[] bs = bos.toByteArray();
+ Headers hds = t.getResponseHeaders();
+ hds.set("Content-Type", "image/jpeg");
+ hds.set("Cache-Control", "no-cache");
+ hds.set("Cache-Control", "no-store");
+ t.sendResponseHeaders(200, bs.length);
+ OutputStream os = t.getResponseBody();
+ os.write(bs);
+ os.close();
+
+ if(s_logger.isInfoEnabled())
+ s_logger.info("Console not ready, sent dummy JPG response");
+ return;
+ }
+
+ {
+ Image scaledImage = viewer.getClientScaledImage(width, height);
+ BufferedImage bufferedImage = new BufferedImage(width, height,
+ BufferedImage.TYPE_3BYTE_BGR);
+ Graphics2D bufImageGraphics = bufferedImage.createGraphics();
+ bufImageGraphics.drawImage(scaledImage, 0, 0, null);
+ ByteArrayOutputStream bos = new ByteArrayOutputStream(8196);
+ javax.imageio.ImageIO.write(bufferedImage, "jpg", bos);
+ byte[] bs = bos.toByteArray();
+ Headers hds = t.getResponseHeaders();
+ hds.set("Content-Type", "image/jpeg");
+ hds.set("Cache-Control", "no-cache");
+ hds.set("Cache-Control", "no-store");
+ t.sendResponseHeaders(200, bs.length);
+ OutputStream os = t.getResponseBody();
+ os.write(bs);
+ os.close();
+ }
+ }
+
+ public static BufferedImage generateTextImage(int w, int h, String text) {
+ BufferedImage img = new BufferedImage(w, h, BufferedImage.TYPE_3BYTE_BGR);
+ Graphics2D g = img.createGraphics();
+ g.setColor(Color.BLACK);
+ g.fillRect(0, 0, w, h);
+ g.setColor(Color.WHITE);
+ try {
+ g.setFont(new Font(null, Font.PLAIN, 12));
+ FontMetrics fm = g.getFontMetrics();
+ int textWidth = fm.stringWidth(text);
+ int startx = (w-textWidth) / 2;
+ if(startx < 0)
+ startx = 0;
+ g.drawString(text, startx, h/2);
+ } catch (Throwable e) {
+ s_logger.warn("Problem in generating text to thumnail image, return blank image");
+ }
+ return img;
+ }
+
+ public static Map getQueryMap(String query) {
+ String[] params = query.split("&");
+ Map map = new HashMap();
+ for (String param : params) {
+ String name = param.split("=")[0];
+ String value = param.split("=")[1];
+ map.put(name, value);
+ }
+ return map;
+ }
+}
diff --git a/console-proxy/src/com/cloud/consoleproxy/InputEventType.java b/console-proxy/src/com/cloud/consoleproxy/InputEventType.java
index b0bf8ebc381..4a5aff16bcf 100644
--- a/console-proxy/src/com/cloud/consoleproxy/InputEventType.java
+++ b/console-proxy/src/com/cloud/consoleproxy/InputEventType.java
@@ -14,45 +14,45 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-package com.cloud.consoleproxy;
-
-public enum InputEventType {
- MOUSE_MOVE(1),
- MOUSE_DOWN(2),
- MOUSE_UP(3),
- KEY_PRESS(4),
- KEY_DOWN(5),
- KEY_UP(6),
- MOUSE_DBLCLICK(8);
-
- int eventCode;
- private InputEventType(int eventCode) {
- this.eventCode = eventCode;
- }
-
- public int getEventCode() {
- return eventCode;
- }
-
- public static InputEventType fromEventCode(int eventCode) {
- switch(eventCode) {
- case 1 :
- return MOUSE_MOVE;
- case 2 :
- return MOUSE_DOWN;
- case 3 :
- return MOUSE_UP;
- case 4 :
- return KEY_PRESS;
- case 5 :
- return KEY_DOWN;
- case 6 :
- return KEY_UP;
- case 8 :
- return MOUSE_DBLCLICK;
- default :
- break;
- }
- throw new IllegalArgumentException("Unsupport event code: " + eventCode);
- }
-}
+package com.cloud.consoleproxy;
+
+public enum InputEventType {
+ MOUSE_MOVE(1),
+ MOUSE_DOWN(2),
+ MOUSE_UP(3),
+ KEY_PRESS(4),
+ KEY_DOWN(5),
+ KEY_UP(6),
+ MOUSE_DBLCLICK(8);
+
+ int eventCode;
+ private InputEventType(int eventCode) {
+ this.eventCode = eventCode;
+ }
+
+ public int getEventCode() {
+ return eventCode;
+ }
+
+ public static InputEventType fromEventCode(int eventCode) {
+ switch(eventCode) {
+ case 1 :
+ return MOUSE_MOVE;
+ case 2 :
+ return MOUSE_DOWN;
+ case 3 :
+ return MOUSE_UP;
+ case 4 :
+ return KEY_PRESS;
+ case 5 :
+ return KEY_DOWN;
+ case 6 :
+ return KEY_UP;
+ case 8 :
+ return MOUSE_DBLCLICK;
+ default :
+ break;
+ }
+ throw new IllegalArgumentException("Unsupport event code: " + eventCode);
+ }
+}
diff --git a/console-proxy/src/com/cloud/consoleproxy/util/ITileScanListener.java b/console-proxy/src/com/cloud/consoleproxy/util/ITileScanListener.java
index 547b13cd60a..2ff82d7242f 100644
--- a/console-proxy/src/com/cloud/consoleproxy/util/ITileScanListener.java
+++ b/console-proxy/src/com/cloud/consoleproxy/util/ITileScanListener.java
@@ -14,12 +14,12 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-package com.cloud.consoleproxy.util;
-
-import java.awt.Rectangle;
-import java.util.List;
-
-public interface ITileScanListener {
- boolean onTileChange(Rectangle rowMergedRect, int row, int col);
- void onRegionChange(List regionList);
-}
+package com.cloud.consoleproxy.util;
+
+import java.awt.Rectangle;
+import java.util.List;
+
+public interface ITileScanListener {
+ boolean onTileChange(Rectangle rowMergedRect, int row, int col);
+ void onRegionChange(List regionList);
+}
diff --git a/console-proxy/src/com/cloud/consoleproxy/util/ImageHelper.java b/console-proxy/src/com/cloud/consoleproxy/util/ImageHelper.java
index 42fb59e48a7..bb7373e78b2 100644
--- a/console-proxy/src/com/cloud/consoleproxy/util/ImageHelper.java
+++ b/console-proxy/src/com/cloud/consoleproxy/util/ImageHelper.java
@@ -14,19 +14,19 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-package com.cloud.consoleproxy.util;
-
-import java.awt.image.BufferedImage;
-import java.io.ByteArrayOutputStream;
-import java.io.IOException;
-
-public class ImageHelper {
- public static byte[] jpegFromImage(BufferedImage image) throws IOException {
- ByteArrayOutputStream bos = new ByteArrayOutputStream(128000);
- javax.imageio.ImageIO.write(image, "jpg", bos);
-
- byte[] jpegBits = bos.toByteArray();
- bos.close();
- return jpegBits;
- }
-}
+package com.cloud.consoleproxy.util;
+
+import java.awt.image.BufferedImage;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+public class ImageHelper {
+ public static byte[] jpegFromImage(BufferedImage image) throws IOException {
+ ByteArrayOutputStream bos = new ByteArrayOutputStream(128000);
+ javax.imageio.ImageIO.write(image, "jpg", bos);
+
+ byte[] jpegBits = bos.toByteArray();
+ bos.close();
+ return jpegBits;
+ }
+}
diff --git a/console-proxy/src/com/cloud/consoleproxy/util/Logger.java b/console-proxy/src/com/cloud/consoleproxy/util/Logger.java
index 2392a98751b..f4357bd4bc4 100644
--- a/console-proxy/src/com/cloud/consoleproxy/util/Logger.java
+++ b/console-proxy/src/com/cloud/consoleproxy/util/Logger.java
@@ -14,210 +14,210 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-package com.cloud.consoleproxy.util;
-
-// logger facility for dynamic switch between console logger used in Applet and log4j based logger
-public class Logger {
- private static LoggerFactory factory = null;
-
- public static final int LEVEL_TRACE = 1;
- public static final int LEVEL_DEBUG = 2;
- public static final int LEVEL_INFO = 3;
- public static final int LEVEL_WARN = 4;
- public static final int LEVEL_ERROR = 5;
-
- private Class> clazz;
- private Logger logger;
-
- private static int level = LEVEL_INFO;
-
- public static Logger getLogger(Class> clazz) {
- return new Logger(clazz);
- }
-
- public static void setFactory(LoggerFactory f) {
- factory = f;
- }
-
- public static void setLevel(int l) {
- level = l;
- }
-
- public Logger(Class> clazz) {
- this.clazz = clazz;
- }
-
- protected Logger() {
- }
-
- public boolean isTraceEnabled() {
- if(factory != null) {
- if(logger == null)
- logger = factory.getLogger(clazz);
-
- return logger.isTraceEnabled();
- }
- return level <= LEVEL_TRACE;
- }
-
- public boolean isDebugEnabled() {
- if(factory != null) {
- if(logger == null)
- logger = factory.getLogger(clazz);
-
- return logger.isDebugEnabled();
- }
- return level <= LEVEL_DEBUG;
- }
-
- public boolean isInfoEnabled() {
- if(factory != null) {
- if(logger == null)
- logger = factory.getLogger(clazz);
-
- return logger.isInfoEnabled();
- }
- return level <= LEVEL_INFO;
- }
-
- public void trace(Object message) {
-
- if(factory != null) {
- if(logger == null)
- logger = factory.getLogger(clazz);
-
- logger.trace(message);
- } else {
- if(level <= LEVEL_TRACE)
- System.out.println(message);
- }
- }
-
- public void trace(Object message, Throwable exception) {
- if(factory != null) {
- if(logger == null)
- logger = factory.getLogger(clazz);
-
- logger.trace(message, exception);
- } else {
- if(level <= LEVEL_TRACE) {
- System.out.println(message);
- if (exception != null) {
- exception.printStackTrace(System.out);
- }
- }
- }
- }
-
- public void info(Object message) {
- if(factory != null) {
- if(logger == null)
- logger = factory.getLogger(clazz);
-
- logger.info(message);
- } else {
- if(level <= LEVEL_INFO)
- System.out.println(message);
- }
- }
-
- public void info(Object message, Throwable exception) {
- if(factory != null) {
- if(logger == null)
- logger = factory.getLogger(clazz);
-
- logger.info(message, exception);
- } else {
- if(level <= LEVEL_INFO) {
- System.out.println(message);
- if (exception != null) {
- exception.printStackTrace(System.out);
- }
- }
- }
- }
-
- public void debug(Object message) {
- if(factory != null) {
- if(logger == null)
- logger = factory.getLogger(clazz);
-
- logger.debug(message);
- } else {
- if(level <= LEVEL_DEBUG)
- System.out.println(message);
- }
- }
-
- public void debug(Object message, Throwable exception) {
- if(factory != null) {
- if(logger == null)
- logger = factory.getLogger(clazz);
-
- logger.debug(message, exception);
- } else {
- if(level <= LEVEL_DEBUG) {
- System.out.println(message);
- if (exception != null) {
- exception.printStackTrace(System.out);
- }
- }
- }
- }
-
- public void warn(Object message) {
- if(factory != null) {
- if(logger == null)
- logger = factory.getLogger(clazz);
-
- logger.warn(message);
- } else {
- if(level <= LEVEL_WARN)
- System.out.println(message);
- }
- }
-
- public void warn(Object message, Throwable exception) {
- if(factory != null) {
- if(logger == null)
- logger = factory.getLogger(clazz);
-
- logger.warn(message, exception);
- } else {
- if(level <= LEVEL_WARN) {
- System.out.println(message);
- if (exception != null) {
- exception.printStackTrace(System.out);
- }
- }
- }
- }
-
- public void error(Object message) {
- if(factory != null) {
- if(logger == null)
- logger = factory.getLogger(clazz);
-
- logger.error(message);
- } else {
- if(level <= LEVEL_ERROR)
- System.out.println(message);
- }
- }
-
- public void error(Object message, Throwable exception) {
- if(factory != null) {
- if(logger == null)
- logger = factory.getLogger(clazz);
-
- logger.error(message, exception);
- } else {
- if(level <= LEVEL_ERROR) {
- System.out.println(message);
- if (exception != null) {
- exception.printStackTrace(System.out);
- }
- }
- }
- }
-}
+package com.cloud.consoleproxy.util;
+
+// logger facility for dynamic switch between console logger used in Applet and log4j based logger
+public class Logger {
+ private static LoggerFactory factory = null;
+
+ public static final int LEVEL_TRACE = 1;
+ public static final int LEVEL_DEBUG = 2;
+ public static final int LEVEL_INFO = 3;
+ public static final int LEVEL_WARN = 4;
+ public static final int LEVEL_ERROR = 5;
+
+ private Class> clazz;
+ private Logger logger;
+
+ private static int level = LEVEL_INFO;
+
+ public static Logger getLogger(Class> clazz) {
+ return new Logger(clazz);
+ }
+
+ public static void setFactory(LoggerFactory f) {
+ factory = f;
+ }
+
+ public static void setLevel(int l) {
+ level = l;
+ }
+
+ public Logger(Class> clazz) {
+ this.clazz = clazz;
+ }
+
+ protected Logger() {
+ }
+
+ public boolean isTraceEnabled() {
+ if(factory != null) {
+ if(logger == null)
+ logger = factory.getLogger(clazz);
+
+ return logger.isTraceEnabled();
+ }
+ return level <= LEVEL_TRACE;
+ }
+
+ public boolean isDebugEnabled() {
+ if(factory != null) {
+ if(logger == null)
+ logger = factory.getLogger(clazz);
+
+ return logger.isDebugEnabled();
+ }
+ return level <= LEVEL_DEBUG;
+ }
+
+ public boolean isInfoEnabled() {
+ if(factory != null) {
+ if(logger == null)
+ logger = factory.getLogger(clazz);
+
+ return logger.isInfoEnabled();
+ }
+ return level <= LEVEL_INFO;
+ }
+
+ public void trace(Object message) {
+
+ if(factory != null) {
+ if(logger == null)
+ logger = factory.getLogger(clazz);
+
+ logger.trace(message);
+ } else {
+ if(level <= LEVEL_TRACE)
+ System.out.println(message);
+ }
+ }
+
+ public void trace(Object message, Throwable exception) {
+ if(factory != null) {
+ if(logger == null)
+ logger = factory.getLogger(clazz);
+
+ logger.trace(message, exception);
+ } else {
+ if(level <= LEVEL_TRACE) {
+ System.out.println(message);
+ if (exception != null) {
+ exception.printStackTrace(System.out);
+ }
+ }
+ }
+ }
+
+ public void info(Object message) {
+ if(factory != null) {
+ if(logger == null)
+ logger = factory.getLogger(clazz);
+
+ logger.info(message);
+ } else {
+ if(level <= LEVEL_INFO)
+ System.out.println(message);
+ }
+ }
+
+ public void info(Object message, Throwable exception) {
+ if(factory != null) {
+ if(logger == null)
+ logger = factory.getLogger(clazz);
+
+ logger.info(message, exception);
+ } else {
+ if(level <= LEVEL_INFO) {
+ System.out.println(message);
+ if (exception != null) {
+ exception.printStackTrace(System.out);
+ }
+ }
+ }
+ }
+
+ public void debug(Object message) {
+ if(factory != null) {
+ if(logger == null)
+ logger = factory.getLogger(clazz);
+
+ logger.debug(message);
+ } else {
+ if(level <= LEVEL_DEBUG)
+ System.out.println(message);
+ }
+ }
+
+ public void debug(Object message, Throwable exception) {
+ if(factory != null) {
+ if(logger == null)
+ logger = factory.getLogger(clazz);
+
+ logger.debug(message, exception);
+ } else {
+ if(level <= LEVEL_DEBUG) {
+ System.out.println(message);
+ if (exception != null) {
+ exception.printStackTrace(System.out);
+ }
+ }
+ }
+ }
+
+ public void warn(Object message) {
+ if(factory != null) {
+ if(logger == null)
+ logger = factory.getLogger(clazz);
+
+ logger.warn(message);
+ } else {
+ if(level <= LEVEL_WARN)
+ System.out.println(message);
+ }
+ }
+
+ public void warn(Object message, Throwable exception) {
+ if(factory != null) {
+ if(logger == null)
+ logger = factory.getLogger(clazz);
+
+ logger.warn(message, exception);
+ } else {
+ if(level <= LEVEL_WARN) {
+ System.out.println(message);
+ if (exception != null) {
+ exception.printStackTrace(System.out);
+ }
+ }
+ }
+ }
+
+ public void error(Object message) {
+ if(factory != null) {
+ if(logger == null)
+ logger = factory.getLogger(clazz);
+
+ logger.error(message);
+ } else {
+ if(level <= LEVEL_ERROR)
+ System.out.println(message);
+ }
+ }
+
+ public void error(Object message, Throwable exception) {
+ if(factory != null) {
+ if(logger == null)
+ logger = factory.getLogger(clazz);
+
+ logger.error(message, exception);
+ } else {
+ if(level <= LEVEL_ERROR) {
+ System.out.println(message);
+ if (exception != null) {
+ exception.printStackTrace(System.out);
+ }
+ }
+ }
+ }
+}
diff --git a/console-proxy/src/com/cloud/consoleproxy/util/LoggerFactory.java b/console-proxy/src/com/cloud/consoleproxy/util/LoggerFactory.java
index fa0d3cfcb31..121411adf16 100644
--- a/console-proxy/src/com/cloud/consoleproxy/util/LoggerFactory.java
+++ b/console-proxy/src/com/cloud/consoleproxy/util/LoggerFactory.java
@@ -14,8 +14,8 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-package com.cloud.consoleproxy.util;
-
-public interface LoggerFactory {
- Logger getLogger(Class> clazz);
-}
+package com.cloud.consoleproxy.util;
+
+public interface LoggerFactory {
+ Logger getLogger(Class> clazz);
+}
diff --git a/console-proxy/src/com/cloud/consoleproxy/util/RawHTTP.java b/console-proxy/src/com/cloud/consoleproxy/util/RawHTTP.java
index eeba34532de..c77b5511270 100644
--- a/console-proxy/src/com/cloud/consoleproxy/util/RawHTTP.java
+++ b/console-proxy/src/com/cloud/consoleproxy/util/RawHTTP.java
@@ -14,236 +14,236 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-package com.cloud.consoleproxy.util;
-
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.Socket;
-import java.security.KeyManagementException;
-import java.security.NoSuchAlgorithmException;
-import java.security.NoSuchProviderException;
-import java.security.SecureRandom;
-import java.security.cert.X509Certificate;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-import javax.net.SocketFactory;
-import javax.net.ssl.SSLContext;
-import javax.net.ssl.SSLSocket;
-import javax.net.ssl.TrustManager;
-import javax.net.ssl.X509TrustManager;
-
-//
-// This file is originally from XenConsole with modifications
-//
-
-/**
- * Send an HTTP CONNECT or PUT request to a XenAPI host with a Session ID,
- * return the connected socket and the Task ID. Used for tunnelling VNC
- * connections and import/export operations.
- */
-public final class RawHTTP {
- private static final Logger s_logger = Logger.getLogger(RawHTTP.class);
-
- private static final Pattern END_PATTERN = Pattern.compile("^\r\n$");
- private static final Pattern HEADER_PATTERN = Pattern
- .compile("^([A-Z_a-z0-9-]+):\\s*(.*)\r\n$");
- private static final Pattern HTTP_PATTERN = Pattern
- .compile("^HTTP/\\d+\\.\\d+ (\\d*) (.*)\r\n$");
-
- /**
- * @uml.property name="command"
- */
- private final String command;
- /**
- * @uml.property name="host"
- */
- private final String host;
- /**
- * @uml.property name="port"
- */
- private final int port;
- /**
- * @uml.property name="path"
- */
- private final String path;
- /**
- * @uml.property name="session"
- */
- private final String session;
- /**
- * @uml.property name="useSSL"
- */
- private final boolean useSSL;
-
- /**
- * @uml.property name="responseHeaders"
- * @uml.associationEnd qualifier="group:java.lang.String java.lang.String"
- */
- private final Map responseHeaders = new HashMap();
-
- /**
- * @uml.property name="ic"
- */
- private InputStream ic;
- /**
- * @uml.property name="oc"
- */
- private OutputStream oc;
- /**
- * @uml.property name="s"
- */
- private Socket s;
-
- public InputStream getInputStream() {
- return ic;
- }
-
- public OutputStream getOutputStream() {
- return oc;
- }
-
- public Socket getSocket() {
- return s;
- }
-
- public RawHTTP(String command, String host, int port, String path,
- String session, boolean useSSL) {
- this.command = command;
- this.host = host;
- this.port = port;
- this.path = path;
- this.session = session;
- this.useSSL = useSSL;
- }
-
- private static final TrustManager[] trustAllCerts = new TrustManager[] {
- new X509TrustManager() {
- public X509Certificate[] getAcceptedIssuers() {
- return null;
- }
-
- public void checkClientTrusted(X509Certificate[] certs, String authType) {
- }
-
- public void checkServerTrusted(X509Certificate[] certs, String authType) {
- }
- }
- };
-
- private Socket _getSocket() throws IOException {
- if (useSSL) {
- SSLContext context = getClientSSLContext();
- if(context == null)
- throw new IOException("Unable to setup SSL context");
-
- SSLSocket ssl = null;
- try {
- context.init(null, trustAllCerts, new SecureRandom());
- SocketFactory factory = context.getSocketFactory();
- ssl = (SSLSocket) factory.createSocket(host, port);
- /* ssl.setSSLParameters(context.getDefaultSSLParameters()); */
- } catch (IOException e) {
- s_logger.error("IOException: " + e.getMessage(), e);
- throw e;
- } catch (KeyManagementException e) {
- s_logger.error("KeyManagementException: " + e.getMessage(), e);
- }
- return ssl;
- } else {
- return new Socket(host, port);
- }
- }
-
- public Socket connect() throws IOException {
- String[] headers = makeHeaders();
- s = _getSocket();
- try {
- oc = s.getOutputStream();
- for (String header : headers) {
- oc.write(header.getBytes());
- oc.write("\r\n".getBytes());
- }
- oc.flush();
- ic = s.getInputStream();
- while (true) {
- String line = readline(ic);
-
- Matcher m = END_PATTERN.matcher(line);
- if (m.matches()) {
- return s;
- }
-
- m = HEADER_PATTERN.matcher(line);
- if (m.matches()) {
- responseHeaders.put(m.group(1), m.group(2));
- continue;
- }
-
- m = HTTP_PATTERN.matcher(line);
- if (m.matches()) {
- String status_code = m.group(1);
- String reason_phrase = m.group(2);
- if (!"200".equals(status_code)) {
- throw new IOException("HTTP status " + status_code
- + " " + reason_phrase);
- }
- } else {
- throw new IOException("Unknown HTTP line " + line);
- }
- }
- } catch (IOException exn) {
- s.close();
- throw exn;
- } catch (RuntimeException exn) {
- s.close();
- throw exn;
- }
- }
-
- public Map getResponseHeaders() {
- return responseHeaders;
- }
-
- private String[] makeHeaders() {
- String[] headers = { String.format("%s %s HTTP/1.0", command, path),
- String.format("Host: %s", host),
- String.format("Cookie: session_id=%s", session), "" };
- return headers;
- }
-
- private static String readline(InputStream ic) throws IOException {
- String result = "";
- while (true) {
- try {
- int c = ic.read();
-
- if (c == -1) {
- return result;
- }
- result = result + (char) c;
- if (c == 0x0a /* LF */) {
- return result;
- }
- } catch (IOException e) {
- ic.close();
- throw e;
- }
- }
- }
-
- private SSLContext getClientSSLContext() {
- SSLContext sslContext = null;
- try {
- sslContext = SSLContext.getInstance("SSL", "SunJSSE");
- } catch (NoSuchAlgorithmException e) {
- s_logger.error("Unexpected exception ", e);
- } catch (NoSuchProviderException e) {
- s_logger.error("Unexpected exception ", e);
- }
- return sslContext;
- }
-}
+package com.cloud.consoleproxy.util;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.Socket;
+import java.security.KeyManagementException;
+import java.security.NoSuchAlgorithmException;
+import java.security.NoSuchProviderException;
+import java.security.SecureRandom;
+import java.security.cert.X509Certificate;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import javax.net.SocketFactory;
+import javax.net.ssl.SSLContext;
+import javax.net.ssl.SSLSocket;
+import javax.net.ssl.TrustManager;
+import javax.net.ssl.X509TrustManager;
+
+//
+// This file is originally from XenConsole with modifications
+//
+
+/**
+ * Send an HTTP CONNECT or PUT request to a XenAPI host with a Session ID,
+ * return the connected socket and the Task ID. Used for tunnelling VNC
+ * connections and import/export operations.
+ */
+public final class RawHTTP {
+ private static final Logger s_logger = Logger.getLogger(RawHTTP.class);
+
+ private static final Pattern END_PATTERN = Pattern.compile("^\r\n$");
+ private static final Pattern HEADER_PATTERN = Pattern
+ .compile("^([A-Z_a-z0-9-]+):\\s*(.*)\r\n$");
+ private static final Pattern HTTP_PATTERN = Pattern
+ .compile("^HTTP/\\d+\\.\\d+ (\\d*) (.*)\r\n$");
+
+ /**
+ * @uml.property name="command"
+ */
+ private final String command;
+ /**
+ * @uml.property name="host"
+ */
+ private final String host;
+ /**
+ * @uml.property name="port"
+ */
+ private final int port;
+ /**
+ * @uml.property name="path"
+ */
+ private final String path;
+ /**
+ * @uml.property name="session"
+ */
+ private final String session;
+ /**
+ * @uml.property name="useSSL"
+ */
+ private final boolean useSSL;
+
+ /**
+ * @uml.property name="responseHeaders"
+ * @uml.associationEnd qualifier="group:java.lang.String java.lang.String"
+ */
+ private final Map responseHeaders = new HashMap();
+
+ /**
+ * @uml.property name="ic"
+ */
+ private InputStream ic;
+ /**
+ * @uml.property name="oc"
+ */
+ private OutputStream oc;
+ /**
+ * @uml.property name="s"
+ */
+ private Socket s;
+
+ public InputStream getInputStream() {
+ return ic;
+ }
+
+ public OutputStream getOutputStream() {
+ return oc;
+ }
+
+ public Socket getSocket() {
+ return s;
+ }
+
+ public RawHTTP(String command, String host, int port, String path,
+ String session, boolean useSSL) {
+ this.command = command;
+ this.host = host;
+ this.port = port;
+ this.path = path;
+ this.session = session;
+ this.useSSL = useSSL;
+ }
+
+ private static final TrustManager[] trustAllCerts = new TrustManager[] {
+ new X509TrustManager() {
+ public X509Certificate[] getAcceptedIssuers() {
+ return null;
+ }
+
+ public void checkClientTrusted(X509Certificate[] certs, String authType) {
+ }
+
+ public void checkServerTrusted(X509Certificate[] certs, String authType) {
+ }
+ }
+ };
+
+ private Socket _getSocket() throws IOException {
+ if (useSSL) {
+ SSLContext context = getClientSSLContext();
+ if(context == null)
+ throw new IOException("Unable to setup SSL context");
+
+ SSLSocket ssl = null;
+ try {
+ context.init(null, trustAllCerts, new SecureRandom());
+ SocketFactory factory = context.getSocketFactory();
+ ssl = (SSLSocket) factory.createSocket(host, port);
+ /* ssl.setSSLParameters(context.getDefaultSSLParameters()); */
+ } catch (IOException e) {
+ s_logger.error("IOException: " + e.getMessage(), e);
+ throw e;
+ } catch (KeyManagementException e) {
+ s_logger.error("KeyManagementException: " + e.getMessage(), e);
+ }
+ return ssl;
+ } else {
+ return new Socket(host, port);
+ }
+ }
+
+ public Socket connect() throws IOException {
+ String[] headers = makeHeaders();
+ s = _getSocket();
+ try {
+ oc = s.getOutputStream();
+ for (String header : headers) {
+ oc.write(header.getBytes());
+ oc.write("\r\n".getBytes());
+ }
+ oc.flush();
+ ic = s.getInputStream();
+ while (true) {
+ String line = readline(ic);
+
+ Matcher m = END_PATTERN.matcher(line);
+ if (m.matches()) {
+ return s;
+ }
+
+ m = HEADER_PATTERN.matcher(line);
+ if (m.matches()) {
+ responseHeaders.put(m.group(1), m.group(2));
+ continue;
+ }
+
+ m = HTTP_PATTERN.matcher(line);
+ if (m.matches()) {
+ String status_code = m.group(1);
+ String reason_phrase = m.group(2);
+ if (!"200".equals(status_code)) {
+ throw new IOException("HTTP status " + status_code
+ + " " + reason_phrase);
+ }
+ } else {
+ throw new IOException("Unknown HTTP line " + line);
+ }
+ }
+ } catch (IOException exn) {
+ s.close();
+ throw exn;
+ } catch (RuntimeException exn) {
+ s.close();
+ throw exn;
+ }
+ }
+
+ public Map getResponseHeaders() {
+ return responseHeaders;
+ }
+
+ private String[] makeHeaders() {
+ String[] headers = { String.format("%s %s HTTP/1.0", command, path),
+ String.format("Host: %s", host),
+ String.format("Cookie: session_id=%s", session), "" };
+ return headers;
+ }
+
+ private static String readline(InputStream ic) throws IOException {
+ String result = "";
+ while (true) {
+ try {
+ int c = ic.read();
+
+ if (c == -1) {
+ return result;
+ }
+ result = result + (char) c;
+ if (c == 0x0a /* LF */) {
+ return result;
+ }
+ } catch (IOException e) {
+ ic.close();
+ throw e;
+ }
+ }
+ }
+
+ private SSLContext getClientSSLContext() {
+ SSLContext sslContext = null;
+ try {
+ sslContext = SSLContext.getInstance("SSL", "SunJSSE");
+ } catch (NoSuchAlgorithmException e) {
+ s_logger.error("Unexpected exception ", e);
+ } catch (NoSuchProviderException e) {
+ s_logger.error("Unexpected exception ", e);
+ }
+ return sslContext;
+ }
+}
diff --git a/console-proxy/src/com/cloud/consoleproxy/util/Region.java b/console-proxy/src/com/cloud/consoleproxy/util/Region.java
index a5860f361b5..a5d1751d63b 100644
--- a/console-proxy/src/com/cloud/consoleproxy/util/Region.java
+++ b/console-proxy/src/com/cloud/consoleproxy/util/Region.java
@@ -14,77 +14,77 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-package com.cloud.consoleproxy.util;
-
-import java.awt.Rectangle;
-import java.util.ArrayList;
-import java.util.List;
-
-public class Region {
- private Rectangle bound;
- private List rectList;
-
- public Region() {
- bound = new Rectangle(0, 0, 0, 0);
- rectList = new ArrayList();
- }
-
- public Region(Rectangle rect) {
- bound = new Rectangle(rect.x, rect.y, rect.width, rect.height);
- rectList = new ArrayList();
- rectList.add(rect);
- }
-
- public Rectangle getBound() {
- return bound;
- }
-
- public void clearBound() {
- assert(rectList.size() == 0);
- bound.x = bound.y = bound.width = bound.height = 0;
- }
-
- public List getRectangles() {
- return rectList;
- }
-
- public boolean add(Rectangle rect) {
- if(bound.isEmpty()) {
- assert(rectList.size() == 0);
- bound.x = rect.x;
- bound.y = rect.y;
- bound.width = rect.width;
- bound.height = rect.height;
-
- rectList.add(rect);
- return true;
- }
-
- Rectangle rcInflated = new Rectangle(rect.x - 1, rect.y- 1, rect.width + 2, rect.height + 2);
- if(!bound.intersects(rcInflated))
- return false;
-
- for(Rectangle r : rectList) {
- if(r.intersects(rcInflated)) {
- if(!r.contains(rect)) {
- enlargeBound(rect);
- rectList.add(rect);
- return true;
- }
- }
- }
- return false;
- }
-
- private void enlargeBound(Rectangle rect) {
- int boundLeft = Math.min(bound.x, rect.x);
- int boundTop = Math.min(bound.y, rect.y);
- int boundRight = Math.max(bound.x + bound.width, rect.x + rect.width);
- int boundBottom = Math.max(bound.y + bound.height, rect.y + rect.height);
-
- bound.x = boundLeft;
- bound.y = boundTop;
- bound.width = boundRight - boundLeft;
- bound.height = boundBottom - boundTop;
- }
-}
+package com.cloud.consoleproxy.util;
+
+import java.awt.Rectangle;
+import java.util.ArrayList;
+import java.util.List;
+
+public class Region {
+ private Rectangle bound;
+ private List rectList;
+
+ public Region() {
+ bound = new Rectangle(0, 0, 0, 0);
+ rectList = new ArrayList();
+ }
+
+ public Region(Rectangle rect) {
+ bound = new Rectangle(rect.x, rect.y, rect.width, rect.height);
+ rectList = new ArrayList();
+ rectList.add(rect);
+ }
+
+ public Rectangle getBound() {
+ return bound;
+ }
+
+ public void clearBound() {
+ assert(rectList.size() == 0);
+ bound.x = bound.y = bound.width = bound.height = 0;
+ }
+
+ public List getRectangles() {
+ return rectList;
+ }
+
+ public boolean add(Rectangle rect) {
+ if(bound.isEmpty()) {
+ assert(rectList.size() == 0);
+ bound.x = rect.x;
+ bound.y = rect.y;
+ bound.width = rect.width;
+ bound.height = rect.height;
+
+ rectList.add(rect);
+ return true;
+ }
+
+ Rectangle rcInflated = new Rectangle(rect.x - 1, rect.y- 1, rect.width + 2, rect.height + 2);
+ if(!bound.intersects(rcInflated))
+ return false;
+
+ for(Rectangle r : rectList) {
+ if(r.intersects(rcInflated)) {
+ if(!r.contains(rect)) {
+ enlargeBound(rect);
+ rectList.add(rect);
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ private void enlargeBound(Rectangle rect) {
+ int boundLeft = Math.min(bound.x, rect.x);
+ int boundTop = Math.min(bound.y, rect.y);
+ int boundRight = Math.max(bound.x + bound.width, rect.x + rect.width);
+ int boundBottom = Math.max(bound.y + bound.height, rect.y + rect.height);
+
+ bound.x = boundLeft;
+ bound.y = boundTop;
+ bound.width = boundRight - boundLeft;
+ bound.height = boundBottom - boundTop;
+ }
+}
diff --git a/console-proxy/src/com/cloud/consoleproxy/util/RegionClassifier.java b/console-proxy/src/com/cloud/consoleproxy/util/RegionClassifier.java
index c4d9b82eb4e..9faa04ea9eb 100644
--- a/console-proxy/src/com/cloud/consoleproxy/util/RegionClassifier.java
+++ b/console-proxy/src/com/cloud/consoleproxy/util/RegionClassifier.java
@@ -14,45 +14,45 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-package com.cloud.consoleproxy.util;
-
-import java.awt.Rectangle;
-import java.util.ArrayList;
-import java.util.List;
-
-public class RegionClassifier {
- private List regionList;
-
- public RegionClassifier() {
- regionList = new ArrayList();
- }
-
- public void add(Rectangle rect) {
- boolean newRegion = true;
- Rectangle rcInflated = new Rectangle(rect.x - 1, rect.y - 1, rect.width + 2, rect.height + 2);
- for(Region region : regionList) {
- if(region.getBound().intersects(rcInflated)) {
- newRegion = false;
- break;
- }
- }
-
- if(newRegion) {
- regionList.add(new Region(rect));
- } else {
- for(Region region : regionList) {
- if(region.add(rect))
- return;
- }
- regionList.add(new Region(rect));
- }
- }
-
- public List getRegionList() {
- return regionList;
- }
-
- public void clear() {
- regionList.clear();
- }
-}
+package com.cloud.consoleproxy.util;
+
+import java.awt.Rectangle;
+import java.util.ArrayList;
+import java.util.List;
+
+public class RegionClassifier {
+ private List regionList;
+
+ public RegionClassifier() {
+ regionList = new ArrayList();
+ }
+
+ public void add(Rectangle rect) {
+ boolean newRegion = true;
+ Rectangle rcInflated = new Rectangle(rect.x - 1, rect.y - 1, rect.width + 2, rect.height + 2);
+ for(Region region : regionList) {
+ if(region.getBound().intersects(rcInflated)) {
+ newRegion = false;
+ break;
+ }
+ }
+
+ if(newRegion) {
+ regionList.add(new Region(rect));
+ } else {
+ for(Region region : regionList) {
+ if(region.add(rect))
+ return;
+ }
+ regionList.add(new Region(rect));
+ }
+ }
+
+ public List getRegionList() {
+ return regionList;
+ }
+
+ public void clear() {
+ regionList.clear();
+ }
+}
diff --git a/console-proxy/src/com/cloud/consoleproxy/util/TileInfo.java b/console-proxy/src/com/cloud/consoleproxy/util/TileInfo.java
index 728f07a700d..933a55a55b0 100644
--- a/console-proxy/src/com/cloud/consoleproxy/util/TileInfo.java
+++ b/console-proxy/src/com/cloud/consoleproxy/util/TileInfo.java
@@ -14,42 +14,42 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-package com.cloud.consoleproxy.util;
-
-import java.awt.Rectangle;
-
-public class TileInfo {
- private int row;
- private int col;
- private Rectangle tileRect;
-
- public TileInfo(int row, int col, Rectangle tileRect) {
- this.row = row;
- this.col = col;
- this.tileRect = tileRect;
- }
-
- public int getRow() {
- return row;
- }
-
- public void setRow(int row) {
- this.row = row;
- }
-
- public int getCol() {
- return col;
- }
-
- public void setCol(int col) {
- this.col = col;
- }
-
- public Rectangle getTileRect() {
- return tileRect;
- }
-
- public void setTileRect(Rectangle tileRect) {
- this.tileRect = tileRect;
- }
-}
+package com.cloud.consoleproxy.util;
+
+import java.awt.Rectangle;
+
+public class TileInfo {
+ private int row;
+ private int col;
+ private Rectangle tileRect;
+
+ public TileInfo(int row, int col, Rectangle tileRect) {
+ this.row = row;
+ this.col = col;
+ this.tileRect = tileRect;
+ }
+
+ public int getRow() {
+ return row;
+ }
+
+ public void setRow(int row) {
+ this.row = row;
+ }
+
+ public int getCol() {
+ return col;
+ }
+
+ public void setCol(int col) {
+ this.col = col;
+ }
+
+ public Rectangle getTileRect() {
+ return tileRect;
+ }
+
+ public void setTileRect(Rectangle tileRect) {
+ this.tileRect = tileRect;
+ }
+}
diff --git a/console-proxy/src/com/cloud/consoleproxy/util/TileTracker.java b/console-proxy/src/com/cloud/consoleproxy/util/TileTracker.java
index 350eebf26a2..b3facb2f88f 100644
--- a/console-proxy/src/com/cloud/consoleproxy/util/TileTracker.java
+++ b/console-proxy/src/com/cloud/consoleproxy/util/TileTracker.java
@@ -14,256 +14,256 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-package com.cloud.consoleproxy.util;
-
-import java.awt.Rectangle;
-import java.util.ArrayList;
-import java.util.List;
-
-public class TileTracker {
-
- // 2 dimension tile status snapshot, a true value means the corresponding tile has been invalidated
- private boolean[][] snapshot;
-
- private int tileWidth = 0;
- private int tileHeight = 0;
- private int trackWidth = 0;
- private int trackHeight = 0;
-
- public TileTracker() {
- }
-
- public int getTileWidth() {
- return tileWidth;
- }
-
- public void setTileWidth(int tileWidth) {
- this.tileWidth = tileWidth;
- }
-
- public int getTileHeight() {
- return tileHeight;
- }
-
- public void setTileHeight(int tileHeight) {
- this.tileHeight = tileHeight;
- }
-
- public int getTrackWidth() {
- return trackWidth;
- }
-
- public void setTrackWidth(int trackWidth) {
- this.trackWidth = trackWidth;
- }
-
- public int getTrackHeight() {
- return trackHeight;
- }
-
- public void setTrackHeight(int trackHeight) {
- this.trackHeight = trackHeight;
- }
-
- public void initTracking(int tileWidth, int tileHeight, int trackWidth, int trackHeight) {
- assert(tileWidth > 0);
- assert(tileHeight > 0);
- assert(trackWidth > 0);
- assert(trackHeight > 0);
- assert(tileWidth <= trackWidth);
- assert(tileHeight <= trackHeight);
-
- this.tileWidth = tileWidth;
- this.tileHeight = tileHeight;
- this.trackWidth = trackWidth;
- this.trackHeight = trackHeight;
-
- int cols = getTileCols();
- int rows = getTileRows();
- snapshot = new boolean[rows][cols];
- for(int i = 0; i < rows; i++)
- for(int j = 0; j < cols; j++)
- snapshot[i][j] = false;
- }
-
- public synchronized void resize(int trackWidth, int trackHeight) {
- assert(tileWidth > 0);
- assert(tileHeight > 0);
- assert(trackWidth > 0);
- assert(trackHeight > 0);
-
- this.trackWidth = trackWidth;
- this.trackHeight = trackHeight;
-
- int cols = getTileCols();
- int rows = getTileRows();
- snapshot = new boolean[rows][cols];
- for(int i = 0; i < rows; i++)
- for(int j = 0; j < cols; j++)
- snapshot[i][j] = true;
- }
-
- public void invalidate(Rectangle rect) {
- setTileFlag(rect, true);
- }
-
- public void validate(Rectangle rect) {
- setTileFlag(rect, false);
- }
-
- public List scan(boolean init) {
- List l = new ArrayList();
-
- synchronized(this) {
- for(int i = 0; i < getTileRows(); i++) {
- for(int j = 0; j < getTileCols(); j++) {
- if(init || snapshot[i][j]) {
- Rectangle rect = new Rectangle();
- rect.y = i*tileHeight;
- rect.x = j*tileWidth;
- rect.width = Math.min(trackWidth - rect.x, tileWidth);
- rect.height = Math.min(trackHeight - rect.y, tileHeight);
-
- l.add(new TileInfo(i, j, rect));
- snapshot[i][j] = false;
- }
- }
- }
-
- return l;
- }
- }
-
- public boolean hasFullCoverage() {
- synchronized(this) {
- for(int i = 0; i < getTileRows(); i++) {
- for(int j = 0; j < getTileCols(); j++) {
- if(!snapshot[i][j])
- return false;
- }
- }
- }
- return true;
- }
-
-
-
- public void initCoverageTest() {
- synchronized(this) {
- for(int i = 0; i < getTileRows(); i++) {
- for(int j = 0; j < getTileCols(); j++) {
- snapshot[i][j] = false;
- }
- }
- }
- }
-
- // listener will be called while holding the object lock, use it
- // with care to avoid deadlock condition being formed
- public synchronized void scan(int nStartRow, int nStartCol, ITileScanListener listener) {
- assert(listener != null);
-
- int cols = getTileCols();
- int rows = getTileRows();
-
- nStartRow = nStartRow % rows;
- nStartCol = nStartCol % cols;
-
- int nPos = nStartRow*cols + nStartCol;
- int nUnits = rows*cols;
- int nStartPos = nPos;
- int nRow;
- int nCol;
- do {
- nRow = nPos / cols;
- nCol = nPos % cols;
-
- if(snapshot[nRow][nCol]) {
- int nEndCol = nCol;
- for(; nEndCol < cols && snapshot[nRow][nEndCol]; nEndCol++) {
- snapshot[nRow][nEndCol] = false;
- }
-
- Rectangle rect = new Rectangle();
- rect.y = nRow*tileHeight;
- rect.height = tileHeight;
- rect.x = nCol*tileWidth;
- rect.width = (nEndCol - nCol)*tileWidth;
-
- if(!listener.onTileChange(rect, nRow, nEndCol))
- break;
- }
-
- nPos = (nPos + 1) % nUnits;
- } while(nPos != nStartPos);
- }
-
- public void capture(ITileScanListener listener) {
- assert(listener != null);
-
- int cols = getTileCols();
- int rows = getTileRows();
-
- RegionClassifier classifier = new RegionClassifier();
- int left, top, right, bottom;
-
- synchronized(this) {
- for(int i = 0; i < rows; i++) {
- top = i*tileHeight;
- bottom = Math.min(top + tileHeight, trackHeight);
- for(int j = 0; j < cols; j++) {
- left = j*tileWidth;
- right = Math.min(left + tileWidth, trackWidth);
-
- if(snapshot[i][j]) {
- snapshot[i][j] = false;
- classifier.add(new Rectangle(left, top, right - left, bottom - top));
- }
- }
- }
- }
- listener.onRegionChange(classifier.getRegionList());
- }
-
- private synchronized void setTileFlag(Rectangle rect, boolean flag) {
- int nStartTileRow;
- int nStartTileCol;
- int nEndTileRow;
- int nEndTileCol;
-
- int cols = getTileCols();
- int rows = getTileRows();
-
- if(rect != null) {
- nStartTileRow = Math.min(getTileYPos(rect.y), rows - 1);
- nStartTileCol = Math.min(getTileXPos(rect.x), cols - 1);
- nEndTileRow = Math.min(getTileYPos(rect.y + rect.height - 1), rows -1);
- nEndTileCol = Math.min(getTileXPos(rect.x + rect.width - 1), cols -1);
- } else {
- nStartTileRow = 0;
- nStartTileCol = 0;
- nEndTileRow = rows - 1;
- nEndTileCol = cols - 1;
- }
-
- for(int i = nStartTileRow; i <= nEndTileRow; i++)
- for(int j = nStartTileCol; j <= nEndTileCol; j++)
- snapshot[i][j] = flag;
- }
-
- private int getTileRows() {
- return (trackHeight + tileHeight - 1) / tileHeight;
- }
-
- private int getTileCols() {
- return (trackWidth + tileWidth - 1) / tileWidth;
- }
-
- private int getTileXPos(int x) {
- return x / tileWidth;
- }
-
- public int getTileYPos(int y) {
- return y / tileHeight;
- }
-}
+package com.cloud.consoleproxy.util;
+
+import java.awt.Rectangle;
+import java.util.ArrayList;
+import java.util.List;
+
+public class TileTracker {
+
+ // 2 dimension tile status snapshot, a true value means the corresponding tile has been invalidated
+ private boolean[][] snapshot;
+
+ private int tileWidth = 0;
+ private int tileHeight = 0;
+ private int trackWidth = 0;
+ private int trackHeight = 0;
+
+ public TileTracker() {
+ }
+
+ public int getTileWidth() {
+ return tileWidth;
+ }
+
+ public void setTileWidth(int tileWidth) {
+ this.tileWidth = tileWidth;
+ }
+
+ public int getTileHeight() {
+ return tileHeight;
+ }
+
+ public void setTileHeight(int tileHeight) {
+ this.tileHeight = tileHeight;
+ }
+
+ public int getTrackWidth() {
+ return trackWidth;
+ }
+
+ public void setTrackWidth(int trackWidth) {
+ this.trackWidth = trackWidth;
+ }
+
+ public int getTrackHeight() {
+ return trackHeight;
+ }
+
+ public void setTrackHeight(int trackHeight) {
+ this.trackHeight = trackHeight;
+ }
+
+ public void initTracking(int tileWidth, int tileHeight, int trackWidth, int trackHeight) {
+ assert(tileWidth > 0);
+ assert(tileHeight > 0);
+ assert(trackWidth > 0);
+ assert(trackHeight > 0);
+ assert(tileWidth <= trackWidth);
+ assert(tileHeight <= trackHeight);
+
+ this.tileWidth = tileWidth;
+ this.tileHeight = tileHeight;
+ this.trackWidth = trackWidth;
+ this.trackHeight = trackHeight;
+
+ int cols = getTileCols();
+ int rows = getTileRows();
+ snapshot = new boolean[rows][cols];
+ for(int i = 0; i < rows; i++)
+ for(int j = 0; j < cols; j++)
+ snapshot[i][j] = false;
+ }
+
+ public synchronized void resize(int trackWidth, int trackHeight) {
+ assert(tileWidth > 0);
+ assert(tileHeight > 0);
+ assert(trackWidth > 0);
+ assert(trackHeight > 0);
+
+ this.trackWidth = trackWidth;
+ this.trackHeight = trackHeight;
+
+ int cols = getTileCols();
+ int rows = getTileRows();
+ snapshot = new boolean[rows][cols];
+ for(int i = 0; i < rows; i++)
+ for(int j = 0; j < cols; j++)
+ snapshot[i][j] = true;
+ }
+
+ public void invalidate(Rectangle rect) {
+ setTileFlag(rect, true);
+ }
+
+ public void validate(Rectangle rect) {
+ setTileFlag(rect, false);
+ }
+
+ public List scan(boolean init) {
+ List l = new ArrayList();
+
+ synchronized(this) {
+ for(int i = 0; i < getTileRows(); i++) {
+ for(int j = 0; j < getTileCols(); j++) {
+ if(init || snapshot[i][j]) {
+ Rectangle rect = new Rectangle();
+ rect.y = i*tileHeight;
+ rect.x = j*tileWidth;
+ rect.width = Math.min(trackWidth - rect.x, tileWidth);
+ rect.height = Math.min(trackHeight - rect.y, tileHeight);
+
+ l.add(new TileInfo(i, j, rect));
+ snapshot[i][j] = false;
+ }
+ }
+ }
+
+ return l;
+ }
+ }
+
+ public boolean hasFullCoverage() {
+ synchronized(this) {
+ for(int i = 0; i < getTileRows(); i++) {
+ for(int j = 0; j < getTileCols(); j++) {
+ if(!snapshot[i][j])
+ return false;
+ }
+ }
+ }
+ return true;
+ }
+
+
+
+ public void initCoverageTest() {
+ synchronized(this) {
+ for(int i = 0; i < getTileRows(); i++) {
+ for(int j = 0; j < getTileCols(); j++) {
+ snapshot[i][j] = false;
+ }
+ }
+ }
+ }
+
+ // listener will be called while holding the object lock, use it
+ // with care to avoid deadlock condition being formed
+ public synchronized void scan(int nStartRow, int nStartCol, ITileScanListener listener) {
+ assert(listener != null);
+
+ int cols = getTileCols();
+ int rows = getTileRows();
+
+ nStartRow = nStartRow % rows;
+ nStartCol = nStartCol % cols;
+
+ int nPos = nStartRow*cols + nStartCol;
+ int nUnits = rows*cols;
+ int nStartPos = nPos;
+ int nRow;
+ int nCol;
+ do {
+ nRow = nPos / cols;
+ nCol = nPos % cols;
+
+ if(snapshot[nRow][nCol]) {
+ int nEndCol = nCol;
+ for(; nEndCol < cols && snapshot[nRow][nEndCol]; nEndCol++) {
+ snapshot[nRow][nEndCol] = false;
+ }
+
+ Rectangle rect = new Rectangle();
+ rect.y = nRow*tileHeight;
+ rect.height = tileHeight;
+ rect.x = nCol*tileWidth;
+ rect.width = (nEndCol - nCol)*tileWidth;
+
+ if(!listener.onTileChange(rect, nRow, nEndCol))
+ break;
+ }
+
+ nPos = (nPos + 1) % nUnits;
+ } while(nPos != nStartPos);
+ }
+
+ public void capture(ITileScanListener listener) {
+ assert(listener != null);
+
+ int cols = getTileCols();
+ int rows = getTileRows();
+
+ RegionClassifier classifier = new RegionClassifier();
+ int left, top, right, bottom;
+
+ synchronized(this) {
+ for(int i = 0; i < rows; i++) {
+ top = i*tileHeight;
+ bottom = Math.min(top + tileHeight, trackHeight);
+ for(int j = 0; j < cols; j++) {
+ left = j*tileWidth;
+ right = Math.min(left + tileWidth, trackWidth);
+
+ if(snapshot[i][j]) {
+ snapshot[i][j] = false;
+ classifier.add(new Rectangle(left, top, right - left, bottom - top));
+ }
+ }
+ }
+ }
+ listener.onRegionChange(classifier.getRegionList());
+ }
+
+ private synchronized void setTileFlag(Rectangle rect, boolean flag) {
+ int nStartTileRow;
+ int nStartTileCol;
+ int nEndTileRow;
+ int nEndTileCol;
+
+ int cols = getTileCols();
+ int rows = getTileRows();
+
+ if(rect != null) {
+ nStartTileRow = Math.min(getTileYPos(rect.y), rows - 1);
+ nStartTileCol = Math.min(getTileXPos(rect.x), cols - 1);
+ nEndTileRow = Math.min(getTileYPos(rect.y + rect.height - 1), rows -1);
+ nEndTileCol = Math.min(getTileXPos(rect.x + rect.width - 1), cols -1);
+ } else {
+ nStartTileRow = 0;
+ nStartTileCol = 0;
+ nEndTileRow = rows - 1;
+ nEndTileCol = cols - 1;
+ }
+
+ for(int i = nStartTileRow; i <= nEndTileRow; i++)
+ for(int j = nStartTileCol; j <= nEndTileCol; j++)
+ snapshot[i][j] = flag;
+ }
+
+ private int getTileRows() {
+ return (trackHeight + tileHeight - 1) / tileHeight;
+ }
+
+ private int getTileCols() {
+ return (trackWidth + tileWidth - 1) / tileWidth;
+ }
+
+ private int getTileXPos(int x) {
+ return x / tileWidth;
+ }
+
+ public int getTileYPos(int y) {
+ return y / tileHeight;
+ }
+}
diff --git a/console-proxy/src/com/cloud/consoleproxy/vnc/BufferedImageCanvas.java b/console-proxy/src/com/cloud/consoleproxy/vnc/BufferedImageCanvas.java
index a92131fc98d..f2fb4bb6b69 100644
--- a/console-proxy/src/com/cloud/consoleproxy/vnc/BufferedImageCanvas.java
+++ b/console-proxy/src/com/cloud/consoleproxy/vnc/BufferedImageCanvas.java
@@ -30,125 +30,121 @@ import com.cloud.consoleproxy.util.ImageHelper;
import com.cloud.consoleproxy.util.TileInfo;
/**
- * A BuffereImageCanvas component represents frame buffer image on the
- * screen. It also notifies its subscribers when screen is repainted.
+ * A BuffereImageCanvas component represents frame buffer image on
+ * the screen. It also notifies its subscribers when screen is repainted.
*/
public class BufferedImageCanvas extends Canvas implements FrameBufferCanvas {
- private static final long serialVersionUID = 1L;
+ private static final long serialVersionUID = 1L;
- // Offline screen buffer
- private BufferedImage offlineImage;
-
- // Cached Graphics2D object for offline screen buffer
- private Graphics2D graphics;
+ // Offline screen buffer
+ private BufferedImage offlineImage;
- private PaintNotificationListener listener;
+ // Cached Graphics2D object for offline screen buffer
+ private Graphics2D graphics;
- public BufferedImageCanvas(PaintNotificationListener listener, int width, int height) {
- super();
- this.listener = listener;
+ private PaintNotificationListener listener;
- setBackground(Color.black);
-
- setFocusable(true);
+ public BufferedImageCanvas(PaintNotificationListener listener, int width, int height) {
+ super();
+ this.listener = listener;
- // Don't intercept TAB key
- setFocusTraversalKeysEnabled(false);
+ setBackground(Color.black);
- setCanvasSize(width, height);
- }
+ setFocusable(true);
- public void setCanvasSize(int width, int height) {
- this.offlineImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
- graphics = offlineImage.createGraphics();
+ // Don't intercept TAB key
+ setFocusTraversalKeysEnabled(false);
- setSize(offlineImage.getWidth(), offlineImage.getHeight());
- }
-
- @Override
- public void update(Graphics g) {
- // Call paint() directly, without clearing screen first
- paint(g);
- }
-
- @Override
- public void paint(Graphics g) {
- // Only part of image, requested with repaint(Rectangle), will be
- // painted on screen.
- synchronized(offlineImage) {
- g.drawImage(offlineImage, 0, 0, this);
+ setCanvasSize(width, height);
}
- // Notify server that update is painted on screen
- listener.imagePaintedOnScreen();
- }
- public BufferedImage getOfflineImage() {
- return offlineImage;
- }
+ public void setCanvasSize(int width, int height) {
+ this.offlineImage = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB);
+ graphics = offlineImage.createGraphics();
- public Graphics2D getOfflineGraphics() {
- return graphics;
- }
-
- public void copyTile(Graphics2D g, int x, int y, Rectangle rc) {
- synchronized(offlineImage) {
- g.drawImage(offlineImage, x, y, x + rc.width, y + rc.height,
- rc.x, rc.y, rc.x + rc.width, rc.y + rc.height, null);
- }
- }
-
- @Override
- public Image getFrameBufferScaledImage(int width, int height) {
- if(offlineImage != null)
- return offlineImage.getScaledInstance(width, height, Image.SCALE_DEFAULT);
- return null;
- }
-
- @Override
- public byte[] getFrameBufferJpeg() {
- int width = 800;
- int height = 600;
-
- width = offlineImage.getWidth();
- height = offlineImage.getHeight();
-
- BufferedImage bufferedImage = new BufferedImage(width, height,
- BufferedImage.TYPE_3BYTE_BGR);
- Graphics2D g = bufferedImage.createGraphics();
- synchronized(offlineImage) {
- g.drawImage(offlineImage, 0, 0, width, height, 0, 0, width, height, null);
- }
-
- byte[] imgBits = null;
- try {
- imgBits = ImageHelper.jpegFromImage(bufferedImage);
- } catch (IOException e) {
- }
- return imgBits;
- }
-
- @Override
- public byte[] getTilesMergedJpeg(List tileList, int tileWidth, int tileHeight) {
- int width = Math.max(tileWidth, tileWidth*tileList.size());
- BufferedImage bufferedImage = new BufferedImage(width, tileHeight,
- BufferedImage.TYPE_3BYTE_BGR);
- Graphics2D g = bufferedImage.createGraphics();
-
- synchronized(offlineImage) {
- int i = 0;
- for(TileInfo tile : tileList) {
- Rectangle rc = tile.getTileRect();
- g.drawImage(offlineImage, i*tileWidth, 0, i*tileWidth + rc.width, rc.height,
- rc.x, rc.y, rc.x + rc.width, rc.y + rc.height, null);
- i++;
- }
- }
-
- byte[] imgBits = null;
- try {
- imgBits = ImageHelper.jpegFromImage(bufferedImage);
- } catch (IOException e) {
- }
- return imgBits;
- }
+ setSize(offlineImage.getWidth(), offlineImage.getHeight());
+ }
+
+ @Override
+ public void update(Graphics g) {
+ // Call paint() directly, without clearing screen first
+ paint(g);
+ }
+
+ @Override
+ public void paint(Graphics g) {
+ // Only part of image, requested with repaint(Rectangle), will be
+ // painted on screen.
+ synchronized (offlineImage) {
+ g.drawImage(offlineImage, 0, 0, this);
+ }
+ // Notify server that update is painted on screen
+ listener.imagePaintedOnScreen();
+ }
+
+ public BufferedImage getOfflineImage() {
+ return offlineImage;
+ }
+
+ public Graphics2D getOfflineGraphics() {
+ return graphics;
+ }
+
+ public void copyTile(Graphics2D g, int x, int y, Rectangle rc) {
+ synchronized (offlineImage) {
+ g.drawImage(offlineImage, x, y, x + rc.width, y + rc.height, rc.x, rc.y, rc.x + rc.width, rc.y + rc.height, null);
+ }
+ }
+
+ @Override
+ public Image getFrameBufferScaledImage(int width, int height) {
+ if (offlineImage != null)
+ return offlineImage.getScaledInstance(width, height, Image.SCALE_DEFAULT);
+ return null;
+ }
+
+ @Override
+ public byte[] getFrameBufferJpeg() {
+ int width = 800;
+ int height = 600;
+
+ width = offlineImage.getWidth();
+ height = offlineImage.getHeight();
+
+ BufferedImage bufferedImage = new BufferedImage(width, height, BufferedImage.TYPE_3BYTE_BGR);
+ Graphics2D g = bufferedImage.createGraphics();
+ synchronized (offlineImage) {
+ g.drawImage(offlineImage, 0, 0, width, height, 0, 0, width, height, null);
+ }
+
+ byte[] imgBits = null;
+ try {
+ imgBits = ImageHelper.jpegFromImage(bufferedImage);
+ } catch (IOException e) {
+ }
+ return imgBits;
+ }
+
+ @Override
+ public byte[] getTilesMergedJpeg(List tileList, int tileWidth, int tileHeight) {
+ int width = Math.max(tileWidth, tileWidth * tileList.size());
+ BufferedImage bufferedImage = new BufferedImage(width, tileHeight, BufferedImage.TYPE_3BYTE_BGR);
+ Graphics2D g = bufferedImage.createGraphics();
+
+ synchronized (offlineImage) {
+ int i = 0;
+ for (TileInfo tile : tileList) {
+ Rectangle rc = tile.getTileRect();
+ g.drawImage(offlineImage, i * tileWidth, 0, i * tileWidth + rc.width, rc.height, rc.x, rc.y, rc.x + rc.width, rc.y + rc.height, null);
+ i++;
+ }
+ }
+
+ byte[] imgBits = null;
+ try {
+ imgBits = ImageHelper.jpegFromImage(bufferedImage);
+ } catch (IOException e) {
+ }
+ return imgBits;
+ }
}
\ No newline at end of file
diff --git a/console-proxy/src/com/cloud/consoleproxy/vnc/FrameBufferCanvas.java b/console-proxy/src/com/cloud/consoleproxy/vnc/FrameBufferCanvas.java
index 3b72f442a06..dcf11461360 100644
--- a/console-proxy/src/com/cloud/consoleproxy/vnc/FrameBufferCanvas.java
+++ b/console-proxy/src/com/cloud/consoleproxy/vnc/FrameBufferCanvas.java
@@ -14,15 +14,17 @@
// KIND, either express or implied. See the License for the
// specific language governing permissions and limitations
// under the License.
-package com.cloud.consoleproxy.vnc;
-
-import java.awt.Image;
-import java.util.List;
-
-import com.cloud.consoleproxy.util.TileInfo;
-
-public interface FrameBufferCanvas {
- Image getFrameBufferScaledImage(int width, int height);
- public byte[] getFrameBufferJpeg();
- public byte[] getTilesMergedJpeg(List tileList, int tileWidth, int tileHeight);
-}
+package com.cloud.consoleproxy.vnc;
+
+import java.awt.Image;
+import java.util.List;
+
+import com.cloud.consoleproxy.util.TileInfo;
+
+public interface FrameBufferCanvas {
+ Image getFrameBufferScaledImage(int width, int height);
+
+ public byte[] getFrameBufferJpeg();
+
+ public byte[] getTilesMergedJpeg(List tileList, int tileWidth, int tileHeight);
+}
diff --git a/console-proxy/src/com/cloud/consoleproxy/vnc/FrameBufferUpdateListener.java b/console-proxy/src/com/cloud/consoleproxy/vnc/FrameBufferUpdateListener.java
index 8dbbe993b14..b8527c5261a 100644
--- a/console-proxy/src/com/cloud/consoleproxy/vnc/FrameBufferUpdateListener.java
+++ b/console-proxy/src/com/cloud/consoleproxy/vnc/FrameBufferUpdateListener.java
@@ -18,9 +18,9 @@ package com.cloud.consoleproxy.vnc;
public interface FrameBufferUpdateListener {
- /**
- * Notify listener, that frame buffer update packet is received, so client is
- * permitted (but not obligated) to ask server to send another update.
- */
- void frameBufferPacketReceived();
+ /**
+ * Notify listener, that frame buffer update packet is received, so client
+ * is permitted (but not obligated) to ask server to send another update.
+ */
+ void frameBufferPacketReceived();
}
diff --git a/console-proxy/src/com/cloud/consoleproxy/vnc/PaintNotificationListener.java b/console-proxy/src/com/cloud/consoleproxy/vnc/PaintNotificationListener.java
index e3bd4af17eb..aaefacb99f2 100644
--- a/console-proxy/src/com/cloud/consoleproxy/vnc/PaintNotificationListener.java
+++ b/console-proxy/src/com/cloud/consoleproxy/vnc/PaintNotificationListener.java
@@ -18,10 +18,10 @@ package com.cloud.consoleproxy.vnc;
public interface PaintNotificationListener {
- /**
- * Notify subscriber that screen is updated, so client can send another frame
- * buffer update request to server.
- */
- void imagePaintedOnScreen();
+ /**
+ * Notify subscriber that screen is updated, so client can send another
+ * frame buffer update request to server.
+ */
+ void imagePaintedOnScreen();
}
diff --git a/console-proxy/src/com/cloud/consoleproxy/vnc/RfbConstants.java b/console-proxy/src/com/cloud/consoleproxy/vnc/RfbConstants.java
index 75499b862ac..18bf47ec1d4 100644
--- a/console-proxy/src/com/cloud/consoleproxy/vnc/RfbConstants.java
+++ b/console-proxy/src/com/cloud/consoleproxy/vnc/RfbConstants.java
@@ -20,62 +20,63 @@ import java.nio.charset.Charset;
public interface RfbConstants {
- public static final String RFB_PROTOCOL_VERSION_MAJOR = "RFB 003.";
-// public static final String VNC_PROTOCOL_VERSION_MINOR = "003";
- public static final String VNC_PROTOCOL_VERSION_MINOR = "003";
- public static final String RFB_PROTOCOL_VERSION = RFB_PROTOCOL_VERSION_MAJOR + VNC_PROTOCOL_VERSION_MINOR;
+ public static final String RFB_PROTOCOL_VERSION_MAJOR = "RFB 003.";
+ // public static final String VNC_PROTOCOL_VERSION_MINOR = "003";
+ public static final String VNC_PROTOCOL_VERSION_MINOR = "003";
+ public static final String RFB_PROTOCOL_VERSION = RFB_PROTOCOL_VERSION_MAJOR + VNC_PROTOCOL_VERSION_MINOR;
- /**
- * Server message types.
- */
- final static int SERVER_FRAMEBUFFER_UPDATE = 0, SERVER_SET_COLOURMAP_ENTRIES = 1, SERVER_BELL = 2, SERVER_CUT_TEXT = 3;
+ /**
+ * Server message types.
+ */
+ final static int SERVER_FRAMEBUFFER_UPDATE = 0, SERVER_SET_COLOURMAP_ENTRIES = 1, SERVER_BELL = 2, SERVER_CUT_TEXT = 3;
- /**
- * Client message types.
- */
- public static final int CLIENT_SET_PIXEL_FORMAT = 0, CLIENT_FIX_COLOURMAP_ENTRIES = 1, CLIENT_SET_ENCODINGS = 2, CLIENT_FRAMEBUFFER_UPDATE_REQUEST = 3,
- CLIENT_KEYBOARD_EVENT = 4, CLIENT_POINTER_EVENT = 5, CLIENT_CUT_TEXT = 6;
+ /**
+ * Client message types.
+ */
+ public static final int CLIENT_SET_PIXEL_FORMAT = 0, CLIENT_FIX_COLOURMAP_ENTRIES = 1, CLIENT_SET_ENCODINGS = 2, CLIENT_FRAMEBUFFER_UPDATE_REQUEST = 3, CLIENT_KEYBOARD_EVENT = 4,
+ CLIENT_POINTER_EVENT = 5, CLIENT_CUT_TEXT = 6;
- /**
- * Server authorization type
- */
- public final static int CONNECTION_FAILED = 0, NO_AUTH = 1, VNC_AUTH = 2;
+ /**
+ * Server authorization type
+ */
+ public final static int CONNECTION_FAILED = 0, NO_AUTH = 1, VNC_AUTH = 2;
- /**
- * Server authorization reply.
- */
- public final static int VNC_AUTH_OK = 0, VNC_AUTH_FAILED = 1, VNC_AUTH_TOO_MANY = 2;
+ /**
+ * Server authorization reply.
+ */
+ public final static int VNC_AUTH_OK = 0, VNC_AUTH_FAILED = 1, VNC_AUTH_TOO_MANY = 2;
- /**
- * Encodings.
- */
- public final static int ENCODING_RAW = 0, ENCODING_COPY_RECT = 1, ENCODING_RRE = 2, ENCODING_CO_RRE = 4, ENCODING_HEXTILE = 5, ENCODING_ZRLE = 16;
+ /**
+ * Encodings.
+ */
+ public final static int ENCODING_RAW = 0, ENCODING_COPY_RECT = 1, ENCODING_RRE = 2, ENCODING_CO_RRE = 4, ENCODING_HEXTILE = 5, ENCODING_ZRLE = 16;
- /**
- * Pseudo-encodings.
- */
- public final static int ENCODING_CURSOR = -239 /*0xFFFFFF11*/, ENCODING_DESKTOP_SIZE = -223 /*0xFFFFFF21*/;
+ /**
+ * Pseudo-encodings.
+ */
+ public final static int ENCODING_CURSOR = -239 /* 0xFFFFFF11 */, ENCODING_DESKTOP_SIZE = -223 /* 0xFFFFFF21 */;
- /**
- * Encodings, which we support.
- */
- public final static int[] SUPPORTED_ENCODINGS_ARRAY = { ENCODING_RAW, ENCODING_COPY_RECT, ENCODING_DESKTOP_SIZE };
+ /**
+ * Encodings, which we support.
+ */
+ public final static int[] SUPPORTED_ENCODINGS_ARRAY = { ENCODING_RAW, ENCODING_COPY_RECT, ENCODING_DESKTOP_SIZE };
- /**
- * Frame buffer update request type: update of whole screen or partial update.
- */
- public static final int FRAMEBUFFER_FULL_UPDATE_REQUEST = 0, FRAMEBUFFER_INCREMENTAL_UPDATE_REQUEST = 1;
+ /**
+ * Frame buffer update request type: update of whole screen or partial
+ * update.
+ */
+ public static final int FRAMEBUFFER_FULL_UPDATE_REQUEST = 0, FRAMEBUFFER_INCREMENTAL_UPDATE_REQUEST = 1;
- public static final int KEY_UP = 0, KEY_DOWN = 1;
+ public static final int KEY_UP = 0, KEY_DOWN = 1;
- public static final int LITTLE_ENDIAN = 0, BIG_ENDIAN = 1;
+ public static final int LITTLE_ENDIAN = 0, BIG_ENDIAN = 1;
- public static final int EXCLUSIVE_ACCESS = 0, SHARED_ACCESS = 1;
+ public static final int EXCLUSIVE_ACCESS = 0, SHARED_ACCESS = 1;
- public static final int PALETTE = 0, TRUE_COLOR = 1;
+ public static final int PALETTE = 0, TRUE_COLOR = 1;
- /**
- * Default charset to use when communicating with server.
- */
- public static final Charset CHARSET = Charset.availableCharsets().get("US-ASCII");
+ /**
+ * Default charset to use when communicating with server.
+ */
+ public static final Charset CHARSET = Charset.availableCharsets().get("US-ASCII");
}
diff --git a/console-proxy/src/com/cloud/consoleproxy/vnc/VncClient.java b/console-proxy/src/com/cloud/consoleproxy/vnc/VncClient.java
index abc9ffaeced..194eec17414 100644
--- a/console-proxy/src/com/cloud/consoleproxy/vnc/VncClient.java
+++ b/console-proxy/src/com/cloud/consoleproxy/vnc/VncClient.java
@@ -39,414 +39,413 @@ import com.cloud.consoleproxy.vnc.packet.client.KeyboardEventPacket;
import com.cloud.consoleproxy.vnc.packet.client.MouseEventPacket;
public class VncClient {
- private static final Logger s_logger = Logger.getLogger(VncClient.class);
+ private static final Logger s_logger = Logger.getLogger(VncClient.class);
- private Socket socket;
- private DataInputStream is;
- private DataOutputStream os;
+ private Socket socket;
+ private DataInputStream is;
+ private DataOutputStream os;
- private VncScreenDescription screen = new VncScreenDescription();
+ private VncScreenDescription screen = new VncScreenDescription();
- private VncClientPacketSender sender;
- private VncServerPacketReceiver receiver;
-
- private boolean noUI = false;
- private ConsoleProxyClientListener clientListener = null;
+ private VncClientPacketSender sender;
+ private VncServerPacketReceiver receiver;
- public static void main(String args[]) {
- if (args.length < 3) {
- printHelpMessage();
- System.exit(1);
+ private boolean noUI = false;
+ private ConsoleProxyClientListener clientListener = null;
+
+ public static void main(String args[]) {
+ if (args.length < 3) {
+ printHelpMessage();
+ System.exit(1);
+ }
+
+ String host = args[0];
+ String port = args[1];
+ String password = args[2];
+
+ try {
+ new VncClient(host, Integer.parseInt(port), password, false, null);
+ } catch (NumberFormatException e) {
+ s_logger.error("Incorrect VNC server port number: " + port + ".");
+ System.exit(1);
+ } catch (UnknownHostException e) {
+ s_logger.error("Incorrect VNC server host name: " + host + ".");
+ System.exit(1);
+ } catch (IOException e) {
+ s_logger.error("Cannot communicate with VNC server: " + e.getMessage());
+ System.exit(1);
+ } catch (Throwable e) {
+ s_logger.error("An error happened: " + e.getMessage());
+ System.exit(1);
+ }
+ System.exit(0);
}
- String host = args[0];
- String port = args[1];
- String password = args[2];
-
- try {
- new VncClient(host, Integer.parseInt(port), password, false, null);
- } catch (NumberFormatException e) {
- s_logger.error("Incorrect VNC server port number: " + port + ".");
- System.exit(1);
- } catch (UnknownHostException e) {
- s_logger.error("Incorrect VNC server host name: " + host + ".");
- System.exit(1);
- } catch (IOException e) {
- s_logger.error("Cannot communicate with VNC server: " + e.getMessage());
- System.exit(1);
- } catch (Throwable e) {
- s_logger.error("An error happened: " + e.getMessage());
- System.exit(1);
- }
- System.exit(0);
- }
-
- private static void printHelpMessage() {
- /* LOG */s_logger.info("Usage: HOST PORT PASSWORD.");
- }
-
- public VncClient(ConsoleProxyClientListener clientListener) {
- this.noUI = true;
- this.clientListener = clientListener;
- }
-
- public VncClient(String host, int port, String password, boolean noUI, ConsoleProxyClientListener clientListener)
- throws UnknownHostException, IOException {
-
- this.noUI = noUI;
- this.clientListener = clientListener;
- connectTo(host, port, password);
- }
-
- public void shutdown() {
- if(sender != null)
- sender.closeConnection();
-
- if(receiver != null)
- receiver.closeConnection();
-
- if(is != null) {
- try {
- is.close();
- } catch (Throwable e) {
- }
- }
-
- if(os != null) {
- try {
- os.close();
- } catch (Throwable e) {
- }
- }
-
- if(socket != null) {
- try {
- socket.close();
- } catch (Throwable e) {
- }
- }
- }
-
- public ConsoleProxyClientListener getClientListener() {
- return clientListener;
- }
-
- public void connectTo(String host, int port, String path,
- String session, boolean useSSL, String sid) throws UnknownHostException, IOException {
- if(port < 0) {
- if(useSSL)
- port = 443;
- else
- port = 80;
- }
-
- RawHTTP tunnel = new RawHTTP("CONNECT", host, port, path, session, useSSL);
- this.socket = tunnel.connect();
- doConnect(sid);
- }
-
- public void connectTo(String host, int port, String password) throws UnknownHostException, IOException {
- // Connect to server
- s_logger.info("Connecting to VNC server " + host + ":" + port + "...");
- this.socket = new Socket(host, port);
- doConnect(password);
- }
-
- private void doConnect(String password) throws IOException {
- is = new DataInputStream(socket.getInputStream());
- os = new DataOutputStream(socket.getOutputStream());
-
- // Initialize connection
- handshake();
- authenticate(password);
- initialize();
-
- s_logger.info("Connecting to VNC server succeeded, start session");
-
- // Run client-to-server packet sender
- sender = new VncClientPacketSender(os, screen, this);
-
- // Create buffered image canvas
- BufferedImageCanvas canvas = new BufferedImageCanvas(sender, screen.getFramebufferWidth(), screen.getFramebufferHeight());
-
- // Subscribe packet sender to various events
- canvas.addMouseListener(sender);
- canvas.addMouseMotionListener(sender);
- canvas.addKeyListener(sender);
-
- Frame frame = null;
- if(!noUI)
- frame = createVncClientMainWindow(canvas, screen.getDesktopName());
-
- new Thread(sender).start();
-
- // Run server-to-client packet receiver
- receiver = new VncServerPacketReceiver(is, canvas, screen, this, sender, clientListener);
- try {
- receiver.run();
- } finally {
- if(frame != null) {
- frame.setVisible(false);
- frame.dispose();
- }
- this.shutdown();
- }
- }
-
- private Frame createVncClientMainWindow(BufferedImageCanvas canvas, String title) {
- // Create AWT windows
- final Frame frame = new Frame(title + " - VNCle");
-
- // Use scrolling pane to support screens, which are larger than ours
- ScrollPane scroller = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED);
- scroller.add(canvas);
- scroller.setSize(screen.getFramebufferWidth(), screen.getFramebufferHeight());
-
- frame.add(scroller);
- frame.pack();
- frame.setVisible(true);
-
- frame.addWindowListener(new WindowAdapter() {
- public void windowClosing(WindowEvent evt) {
- frame.setVisible(false);
- shutdown();
- }
- });
-
- return frame;
- }
-
- /**
- * Handshake with VNC server.
- */
- private void handshake() throws IOException {
-
- // Read protocol version
- byte[] buf = new byte[12];
- is.readFully(buf);
- String rfbProtocol = new String(buf);
-
- // Server should use RFB protocol 3.x
- if (!rfbProtocol.contains(RfbConstants.RFB_PROTOCOL_VERSION_MAJOR)) {
- s_logger.error("Cannot handshake with VNC server. Unsupported protocol version: \"" + rfbProtocol + "\".");
- throw new RuntimeException("Cannot handshake with VNC server. Unsupported protocol version: \"" + rfbProtocol + "\".");
+ private static void printHelpMessage() {
+ /* LOG */s_logger.info("Usage: HOST PORT PASSWORD.");
}
- // Send response: we support RFB 3.3 only
- String ourProtocolString = RfbConstants.RFB_PROTOCOL_VERSION + "\n";
- os.write(ourProtocolString.getBytes());
- os.flush();
- }
-
- /**
- * VNC authentication.
- */
- private void authenticate(String password) throws IOException {
- // Read security type
- int authType = is.readInt();
-
- switch (authType) {
- case RfbConstants.CONNECTION_FAILED: {
- // Server forbids to connect. Read reason and throw exception
-
- int length = is.readInt();
- byte[] buf = new byte[length];
- is.readFully(buf);
- String reason = new String(buf, RfbConstants.CHARSET);
-
- s_logger.error("Authentication to VNC server is failed. Reason: " + reason);
- throw new RuntimeException("Authentication to VNC server is failed. Reason: " + reason);
+ public VncClient(ConsoleProxyClientListener clientListener) {
+ this.noUI = true;
+ this.clientListener = clientListener;
}
- case RfbConstants.NO_AUTH: {
- // Client can connect without authorization. Nothing to do.
- break;
+ public VncClient(String host, int port, String password, boolean noUI, ConsoleProxyClientListener clientListener) throws UnknownHostException, IOException {
+
+ this.noUI = noUI;
+ this.clientListener = clientListener;
+ connectTo(host, port, password);
}
- case RfbConstants.VNC_AUTH: {
- s_logger.info("VNC server requires password authentication");
- doVncAuth(password);
- break;
+ public void shutdown() {
+ if (sender != null)
+ sender.closeConnection();
+
+ if (receiver != null)
+ receiver.closeConnection();
+
+ if (is != null) {
+ try {
+ is.close();
+ } catch (Throwable e) {
+ }
+ }
+
+ if (os != null) {
+ try {
+ os.close();
+ } catch (Throwable e) {
+ }
+ }
+
+ if (socket != null) {
+ try {
+ socket.close();
+ } catch (Throwable e) {
+ }
+ }
}
- default:
- s_logger.error("Unsupported VNC protocol authorization scheme, scheme code: " + authType + ".");
- throw new RuntimeException("Unsupported VNC protocol authorization scheme, scheme code: " + authType + ".");
- }
- }
-
- /**
- * Encode client password and send it to server.
- */
- private void doVncAuth(String password) throws IOException {
-
- // Read challenge
- byte[] challenge = new byte[16];
- is.readFully(challenge);
-
- // Encode challenge with password
- byte[] response;
- try {
- response = encodePassword(challenge, password);
- } catch (Exception e) {
- s_logger.error("Cannot encrypt client password to send to server: " + e.getMessage());
- throw new RuntimeException("Cannot encrypt client password to send to server: " + e.getMessage());
+ public ConsoleProxyClientListener getClientListener() {
+ return clientListener;
}
- // Send encoded challenge
- os.write(response);
- os.flush();
+ public void connectTo(String host, int port, String path, String session, boolean useSSL, String sid) throws UnknownHostException, IOException {
+ if (port < 0) {
+ if (useSSL)
+ port = 443;
+ else
+ port = 80;
+ }
- // Read security result
- int authResult = is.readInt();
-
- switch (authResult) {
- case RfbConstants.VNC_AUTH_OK: {
- // Nothing to do
- break;
+ RawHTTP tunnel = new RawHTTP("CONNECT", host, port, path, session, useSSL);
+ this.socket = tunnel.connect();
+ doConnect(sid);
}
- case RfbConstants.VNC_AUTH_TOO_MANY:
- s_logger.error("Connection to VNC server failed: too many wrong attempts.");
- throw new RuntimeException("Connection to VNC server failed: too many wrong attempts.");
-
- case RfbConstants.VNC_AUTH_FAILED:
- s_logger.error("Connection to VNC server failed: wrong password.");
- throw new RuntimeException("Connection to VNC server failed: wrong password.");
-
- default:
- s_logger.error("Connection to VNC server failed, reason code: " + authResult);
- throw new RuntimeException("Connection to VNC server failed, reason code: " + authResult);
- }
- }
-
- /**
- * Encode password using DES encryption with given challenge.
- *
- * @param challenge
- * a random set of bytes.
- * @param password
- * a password
- * @return DES hash of password and challenge
- */
- public byte[] encodePassword(byte[] challenge, String password) throws Exception {
- // VNC password consist of up to eight ASCII characters.
- byte[] key = { 0, 0, 0, 0, 0, 0, 0, 0 }; // Padding
- byte[] passwordAsciiBytes = password.getBytes(RfbConstants.CHARSET);
- System.arraycopy(passwordAsciiBytes, 0, key, 0, Math.min(password.length(), 8));
-
- // Flip bytes (reverse bits) in key
- for (int i = 0; i < key.length; i++) {
- key[i] = flipByte(key[i]);
+ public void connectTo(String host, int port, String password) throws UnknownHostException, IOException {
+ // Connect to server
+ s_logger.info("Connecting to VNC server " + host + ":" + port + "...");
+ this.socket = new Socket(host, port);
+ doConnect(password);
}
- KeySpec desKeySpec = new DESKeySpec(key);
- SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
- SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec);
- Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");
- cipher.init(Cipher.ENCRYPT_MODE, secretKey);
+ private void doConnect(String password) throws IOException {
+ is = new DataInputStream(socket.getInputStream());
+ os = new DataOutputStream(socket.getOutputStream());
- byte[] response = cipher.doFinal(challenge);
- return response;
- }
+ // Initialize connection
+ handshake();
+ authenticate(password);
+ initialize();
- /**
- * Reverse bits in byte, so least significant bit will be most significant
- * bit. E.g. 01001100 will become 00110010.
- *
- * See also: http://www.vidarholen.net/contents/junk/vnc.html ,
- * http://bytecrafter .blogspot.com/2010/09/des-encryption-as-used-in-vnc.html
- *
- * @param b
- * a byte
- * @return byte in reverse order
- */
- private static byte flipByte(byte b) {
- int b1_8 = (b & 0x1) << 7;
- int b2_7 = (b & 0x2) << 5;
- int b3_6 = (b & 0x4) << 3;
- int b4_5 = (b & 0x8) << 1;
- int b5_4 = (b & 0x10) >>> 1;
- int b6_3 = (b & 0x20) >>> 3;
- int b7_2 = (b & 0x40) >>> 5;
- int b8_1 = (b & 0x80) >>> 7;
- byte c = (byte) (b1_8 | b2_7 | b3_6 | b4_5 | b5_4 | b6_3 | b7_2 | b8_1);
- return c;
- }
+ s_logger.info("Connecting to VNC server succeeded, start session");
- private void initialize() throws IOException {
- // Send client initialization message
- {
- // Send shared flag
- os.writeByte(RfbConstants.EXCLUSIVE_ACCESS);
- os.flush();
+ // Run client-to-server packet sender
+ sender = new VncClientPacketSender(os, screen, this);
+
+ // Create buffered image canvas
+ BufferedImageCanvas canvas = new BufferedImageCanvas(sender, screen.getFramebufferWidth(), screen.getFramebufferHeight());
+
+ // Subscribe packet sender to various events
+ canvas.addMouseListener(sender);
+ canvas.addMouseMotionListener(sender);
+ canvas.addKeyListener(sender);
+
+ Frame frame = null;
+ if (!noUI)
+ frame = createVncClientMainWindow(canvas, screen.getDesktopName());
+
+ new Thread(sender).start();
+
+ // Run server-to-client packet receiver
+ receiver = new VncServerPacketReceiver(is, canvas, screen, this, sender, clientListener);
+ try {
+ receiver.run();
+ } finally {
+ if (frame != null) {
+ frame.setVisible(false);
+ frame.dispose();
+ }
+ this.shutdown();
+ }
}
- // Read server initialization message
- {
- // Read frame buffer size
- int framebufferWidth = is.readUnsignedShort();
- int framebufferHeight = is.readUnsignedShort();
- screen.setFramebufferSize(framebufferWidth, framebufferHeight);
- if(clientListener != null)
- clientListener.onFramebufferSizeChange(framebufferWidth, framebufferHeight);
+ private Frame createVncClientMainWindow(BufferedImageCanvas canvas, String title) {
+ // Create AWT windows
+ final Frame frame = new Frame(title + " - VNCle");
+
+ // Use scrolling pane to support screens, which are larger than ours
+ ScrollPane scroller = new ScrollPane(ScrollPane.SCROLLBARS_AS_NEEDED);
+ scroller.add(canvas);
+ scroller.setSize(screen.getFramebufferWidth(), screen.getFramebufferHeight());
+
+ frame.add(scroller);
+ frame.pack();
+ frame.setVisible(true);
+
+ frame.addWindowListener(new WindowAdapter() {
+ public void windowClosing(WindowEvent evt) {
+ frame.setVisible(false);
+ shutdown();
+ }
+ });
+
+ return frame;
}
- // Read pixel format
- {
- int bitsPerPixel = is.readUnsignedByte();
- int depth = is.readUnsignedByte();
+ /**
+ * Handshake with VNC server.
+ */
+ private void handshake() throws IOException {
- int bigEndianFlag = is.readUnsignedByte();
- int trueColorFlag = is.readUnsignedByte();
+ // Read protocol version
+ byte[] buf = new byte[12];
+ is.readFully(buf);
+ String rfbProtocol = new String(buf);
- int redMax = is.readUnsignedShort();
- int greenMax = is.readUnsignedShort();
- int blueMax = is.readUnsignedShort();
+ // Server should use RFB protocol 3.x
+ if (!rfbProtocol.contains(RfbConstants.RFB_PROTOCOL_VERSION_MAJOR)) {
+ s_logger.error("Cannot handshake with VNC server. Unsupported protocol version: \"" + rfbProtocol + "\".");
+ throw new RuntimeException("Cannot handshake with VNC server. Unsupported protocol version: \"" + rfbProtocol + "\".");
+ }
- int redShift = is.readUnsignedByte();
- int greenShift = is.readUnsignedByte();
- int blueShift = is.readUnsignedByte();
-
- // Skip padding
- is.skipBytes(3);
-
- screen.setPixelFormat(bitsPerPixel, depth, bigEndianFlag, trueColorFlag, redMax, greenMax, blueMax, redShift, greenShift, blueShift);
+ // Send response: we support RFB 3.3 only
+ String ourProtocolString = RfbConstants.RFB_PROTOCOL_VERSION + "\n";
+ os.write(ourProtocolString.getBytes());
+ os.flush();
}
- // Read desktop name
- {
- int length = is.readInt();
- byte buf[] = new byte[length];
- is.readFully(buf);
- String desktopName = new String(buf, RfbConstants.CHARSET);
- screen.setDesktopName(desktopName);
+ /**
+ * VNC authentication.
+ */
+ private void authenticate(String password) throws IOException {
+ // Read security type
+ int authType = is.readInt();
+
+ switch (authType) {
+ case RfbConstants.CONNECTION_FAILED: {
+ // Server forbids to connect. Read reason and throw exception
+
+ int length = is.readInt();
+ byte[] buf = new byte[length];
+ is.readFully(buf);
+ String reason = new String(buf, RfbConstants.CHARSET);
+
+ s_logger.error("Authentication to VNC server is failed. Reason: " + reason);
+ throw new RuntimeException("Authentication to VNC server is failed. Reason: " + reason);
+ }
+
+ case RfbConstants.NO_AUTH: {
+ // Client can connect without authorization. Nothing to do.
+ break;
+ }
+
+ case RfbConstants.VNC_AUTH: {
+ s_logger.info("VNC server requires password authentication");
+ doVncAuth(password);
+ break;
+ }
+
+ default:
+ s_logger.error("Unsupported VNC protocol authorization scheme, scheme code: " + authType + ".");
+ throw new RuntimeException("Unsupported VNC protocol authorization scheme, scheme code: " + authType + ".");
+ }
+ }
+
+ /**
+ * Encode client password and send it to server.
+ */
+ private void doVncAuth(String password) throws IOException {
+
+ // Read challenge
+ byte[] challenge = new byte[16];
+ is.readFully(challenge);
+
+ // Encode challenge with password
+ byte[] response;
+ try {
+ response = encodePassword(challenge, password);
+ } catch (Exception e) {
+ s_logger.error("Cannot encrypt client password to send to server: " + e.getMessage());
+ throw new RuntimeException("Cannot encrypt client password to send to server: " + e.getMessage());
+ }
+
+ // Send encoded challenge
+ os.write(response);
+ os.flush();
+
+ // Read security result
+ int authResult = is.readInt();
+
+ switch (authResult) {
+ case RfbConstants.VNC_AUTH_OK: {
+ // Nothing to do
+ break;
+ }
+
+ case RfbConstants.VNC_AUTH_TOO_MANY:
+ s_logger.error("Connection to VNC server failed: too many wrong attempts.");
+ throw new RuntimeException("Connection to VNC server failed: too many wrong attempts.");
+
+ case RfbConstants.VNC_AUTH_FAILED:
+ s_logger.error("Connection to VNC server failed: wrong password.");
+ throw new RuntimeException("Connection to VNC server failed: wrong password.");
+
+ default:
+ s_logger.error("Connection to VNC server failed, reason code: " + authResult);
+ throw new RuntimeException("Connection to VNC server failed, reason code: " + authResult);
+ }
+ }
+
+ /**
+ * Encode password using DES encryption with given challenge.
+ *
+ * @param challenge
+ * a random set of bytes.
+ * @param password
+ * a password
+ * @return DES hash of password and challenge
+ */
+ public byte[] encodePassword(byte[] challenge, String password) throws Exception {
+ // VNC password consist of up to eight ASCII characters.
+ byte[] key = { 0, 0, 0, 0, 0, 0, 0, 0 }; // Padding
+ byte[] passwordAsciiBytes = password.getBytes(RfbConstants.CHARSET);
+ System.arraycopy(passwordAsciiBytes, 0, key, 0, Math.min(password.length(), 8));
+
+ // Flip bytes (reverse bits) in key
+ for (int i = 0; i < key.length; i++) {
+ key[i] = flipByte(key[i]);
+ }
+
+ KeySpec desKeySpec = new DESKeySpec(key);
+ SecretKeyFactory secretKeyFactory = SecretKeyFactory.getInstance("DES");
+ SecretKey secretKey = secretKeyFactory.generateSecret(desKeySpec);
+ Cipher cipher = Cipher.getInstance("DES/ECB/NoPadding");
+ cipher.init(Cipher.ENCRYPT_MODE, secretKey);
+
+ byte[] response = cipher.doFinal(challenge);
+ return response;
+ }
+
+ /**
+ * Reverse bits in byte, so least significant bit will be most significant
+ * bit. E.g. 01001100 will become 00110010.
+ *
+ * See also: http://www.vidarholen.net/contents/junk/vnc.html ,
+ * http://bytecrafter
+ * .blogspot.com/2010/09/des-encryption-as-used-in-vnc.html
+ *
+ * @param b
+ * a byte
+ * @return byte in reverse order
+ */
+ private static byte flipByte(byte b) {
+ int b1_8 = (b & 0x1) << 7;
+ int b2_7 = (b & 0x2) << 5;
+ int b3_6 = (b & 0x4) << 3;
+ int b4_5 = (b & 0x8) << 1;
+ int b5_4 = (b & 0x10) >>> 1;
+ int b6_3 = (b & 0x20) >>> 3;
+ int b7_2 = (b & 0x40) >>> 5;
+ int b8_1 = (b & 0x80) >>> 7;
+ byte c = (byte) (b1_8 | b2_7 | b3_6 | b4_5 | b5_4 | b6_3 | b7_2 | b8_1);
+ return c;
+ }
+
+ private void initialize() throws IOException {
+ // Send client initialization message
+ {
+ // Send shared flag
+ os.writeByte(RfbConstants.EXCLUSIVE_ACCESS);
+ os.flush();
+ }
+
+ // Read server initialization message
+ {
+ // Read frame buffer size
+ int framebufferWidth = is.readUnsignedShort();
+ int framebufferHeight = is.readUnsignedShort();
+ screen.setFramebufferSize(framebufferWidth, framebufferHeight);
+ if (clientListener != null)
+ clientListener.onFramebufferSizeChange(framebufferWidth, framebufferHeight);
+ }
+
+ // Read pixel format
+ {
+ int bitsPerPixel = is.readUnsignedByte();
+ int depth = is.readUnsignedByte();
+
+ int bigEndianFlag = is.readUnsignedByte();
+ int trueColorFlag = is.readUnsignedByte();
+
+ int redMax = is.readUnsignedShort();
+ int greenMax = is.readUnsignedShort();
+ int blueMax = is.readUnsignedShort();
+
+ int redShift = is.readUnsignedByte();
+ int greenShift = is.readUnsignedByte();
+ int blueShift = is.readUnsignedByte();
+
+ // Skip padding
+ is.skipBytes(3);
+
+ screen.setPixelFormat(bitsPerPixel, depth, bigEndianFlag, trueColorFlag, redMax, greenMax, blueMax, redShift, greenShift, blueShift);
+ }
+
+ // Read desktop name
+ {
+ int length = is.readInt();
+ byte buf[] = new byte[length];
+ is.readFully(buf);
+ String desktopName = new String(buf, RfbConstants.CHARSET);
+ screen.setDesktopName(desktopName);
+ }
+ }
+
+ public FrameBufferCanvas getFrameBufferCanvas() {
+ if (receiver != null)
+ return receiver.getCanvas();
+
+ return null;
+ }
+
+ public void requestUpdate(boolean fullUpdate) {
+ if (fullUpdate)
+ sender.requestFullScreenUpdate();
+ else
+ sender.imagePaintedOnScreen();
+ }
+
+ public void sendClientKeyboardEvent(int event, int code, int modifiers) {
+ sender.sendClientPacket(new KeyboardEventPacket(event, code));
+ }
+
+ public void sendClientMouseEvent(int event, int x, int y, int code, int modifiers) {
+ sender.sendClientPacket(new MouseEventPacket(event, x, y));
+ }
+
+ public boolean isHostConnected() {
+ return receiver != null && receiver.isConnectionAlive();
}
- }
-
- public FrameBufferCanvas getFrameBufferCanvas() {
- if(receiver != null)
- return receiver.getCanvas();
-
- return null;
- }
-
- public void requestUpdate(boolean fullUpdate) {
- if(fullUpdate)
- sender.requestFullScreenUpdate();
- else
- sender.imagePaintedOnScreen();
- }
-
- public void sendClientKeyboardEvent(int event, int code, int modifiers) {
- sender.sendClientPacket(new KeyboardEventPacket(event, code));
- }
-
- public void sendClientMouseEvent(int event, int x, int y, int code, int modifiers) {
- sender.sendClientPacket(new MouseEventPacket(event, x, y));
- }
-
- public boolean isHostConnected() {
- return receiver != null && receiver.isConnectionAlive();
- }
}
diff --git a/console-proxy/src/com/cloud/consoleproxy/vnc/VncClientPacketSender.java b/console-proxy/src/com/cloud/consoleproxy/vnc/VncClientPacketSender.java
index cf15f885e5f..d27b76d3468 100644
--- a/console-proxy/src/com/cloud/consoleproxy/vnc/VncClientPacketSender.java
+++ b/console-proxy/src/com/cloud/consoleproxy/vnc/VncClientPacketSender.java
@@ -35,226 +35,224 @@ import com.cloud.consoleproxy.vnc.packet.client.SetEncodingsPacket;
import com.cloud.consoleproxy.vnc.packet.client.SetPixelFormatPacket;
public class VncClientPacketSender implements Runnable, PaintNotificationListener, KeyListener, MouseListener, MouseMotionListener, FrameBufferUpdateListener {
- private static final Logger s_logger = Logger.getLogger(VncClientPacketSender.class);
+ private static final Logger s_logger = Logger.getLogger(VncClientPacketSender.class);
- // Queue for outgoing packets
- private final BlockingQueue queue = new ArrayBlockingQueue(30);
+ // Queue for outgoing packets
+ private final BlockingQueue queue = new ArrayBlockingQueue(30);
- private final DataOutputStream os;
- private final VncScreenDescription screen;
- private final VncClient vncConnection;
+ private final DataOutputStream os;
+ private final VncScreenDescription screen;
+ private final VncClient vncConnection;
- private boolean connectionAlive = true;
+ private boolean connectionAlive = true;
- // Don't send update request again until we receive next frame buffer update
- private boolean updateRequestSent = false;
+ // Don't send update request again until we receive next frame buffer update
+ private boolean updateRequestSent = false;
- public VncClientPacketSender(DataOutputStream os, VncScreenDescription screen, VncClient vncConnection) {
- this.os = os;
- this.screen = screen;
- this.vncConnection = vncConnection;
+ public VncClientPacketSender(DataOutputStream os, VncScreenDescription screen, VncClient vncConnection) {
+ this.os = os;
+ this.screen = screen;
+ this.vncConnection = vncConnection;
- sendSetPixelFormat();
- sendSetEncodings();
- requestFullScreenUpdate();
- }
-
- public void sendClientPacket(ClientPacket packet) {
- queue.add(packet);
- }
+ sendSetPixelFormat();
+ sendSetEncodings();
+ requestFullScreenUpdate();
+ }
- @Override
- public void run() {
- try {
- while (connectionAlive) {
- ClientPacket packet = queue.poll(1, TimeUnit.SECONDS);
- if (packet != null) {
- packet.write(os);
- os.flush();
+ public void sendClientPacket(ClientPacket packet) {
+ queue.add(packet);
+ }
+
+ @Override
+ public void run() {
+ try {
+ while (connectionAlive) {
+ ClientPacket packet = queue.poll(1, TimeUnit.SECONDS);
+ if (packet != null) {
+ packet.write(os);
+ os.flush();
+ }
+ }
+ } catch (Throwable e) {
+ s_logger.error("Unexpected exception: ", e);
+ if (connectionAlive) {
+ closeConnection();
+ vncConnection.shutdown();
+ }
}
- }
- } catch (Throwable e) {
- s_logger.error("Unexpected exception: ", e);
- if (connectionAlive) {
- closeConnection();
- vncConnection.shutdown();
- }
- }
- }
-
- private void sendSetEncodings() {
- queue.add(new SetEncodingsPacket(RfbConstants.SUPPORTED_ENCODINGS_ARRAY));
- }
-
- private void sendSetPixelFormat() {
- if (!screen.isRGB888_32_LE()) {
- queue.add(new SetPixelFormatPacket(screen, 32, 24, RfbConstants.LITTLE_ENDIAN, RfbConstants.TRUE_COLOR, 255, 255, 255, 16, 8, 0));
- }
- }
-
- public void closeConnection() {
- connectionAlive = false;
- }
-
- public void requestFullScreenUpdate() {
- queue.add(new FramebufferUpdateRequestPacket(RfbConstants.FRAMEBUFFER_FULL_UPDATE_REQUEST, 0, 0, screen.getFramebufferWidth(), screen
- .getFramebufferHeight()));
- updateRequestSent = true;
- }
-
- @Override
- public void imagePaintedOnScreen() {
- if (!updateRequestSent) {
- queue.add(new FramebufferUpdateRequestPacket(RfbConstants.FRAMEBUFFER_INCREMENTAL_UPDATE_REQUEST, 0, 0, screen.getFramebufferWidth(), screen
- .getFramebufferHeight()));
- updateRequestSent = true;
- }
- }
-
- @Override
- public void frameBufferPacketReceived() {
- updateRequestSent = false;
- }
-
- @Override
- public void mouseDragged(MouseEvent e) {
- queue.add(new MouseEventPacket(mapAwtModifiersToVncButtonMask(e.getModifiersEx()), e.getX(), e.getY()));
- }
-
- @Override
- public void mouseMoved(MouseEvent e) {
- queue.add(new MouseEventPacket(mapAwtModifiersToVncButtonMask(e.getModifiersEx()), e.getX(), e.getY()));
- }
-
- @Override
- public void mouseClicked(MouseEvent e) {
- // Nothing to do
- }
-
- @Override
- public void mousePressed(MouseEvent e) {
- queue.add(new MouseEventPacket(mapAwtModifiersToVncButtonMask(e.getModifiersEx()), e.getX(), e.getY()));
- }
-
- @Override
- public void mouseReleased(MouseEvent e) {
- queue.add(new MouseEventPacket(mapAwtModifiersToVncButtonMask(e.getModifiersEx()), e.getX(), e.getY()));
- }
-
- @Override
- public void mouseEntered(MouseEvent e) {
- // Nothing to do
- }
-
- @Override
- public void mouseExited(MouseEvent e) {
- // Nothing to do
- }
-
- /**
- * Current state of buttons 1 to 8 are represented by bits 0 to 7 of
- * button-mask respectively, 0 meaning up, 1 meaning down (pressed). On a
- * conventional mouse, buttons 1, 2 and 3 correspond to the left, middle and
- * right buttons on the mouse. On a wheel mouse, each step of the wheel
- * upwards is represented by a press and release of button 4, and each step
- * downwards is represented by a press and release of button 5.
- *
- * @param modifiers
- * extended modifiers from AWT mouse event
- * @return VNC mouse button mask
- */
- public static int mapAwtModifiersToVncButtonMask(int modifiers) {
- int mask = (((modifiers & MouseEvent.BUTTON1_DOWN_MASK) != 0) ? 0x1 : 0) | (((modifiers & MouseEvent.BUTTON2_DOWN_MASK) != 0) ? 0x2 : 0)
- | (((modifiers & MouseEvent.BUTTON3_DOWN_MASK) != 0) ? 0x4 : 0);
- return mask;
- }
-
- @Override
- public void keyTyped(KeyEvent e) {
- // Do nothing
- }
-
- @Override
- public void keyPressed(KeyEvent e) {
- ClientPacket request = new KeyboardEventPacket(RfbConstants.KEY_DOWN, mapAwtKeyToVncKey(e.getKeyCode()));
- queue.add(request);
- }
-
- @Override
- public void keyReleased(KeyEvent e) {
- ClientPacket request = new KeyboardEventPacket(RfbConstants.KEY_UP, mapAwtKeyToVncKey(e.getKeyCode()));
- queue.add(request);
- }
-
- private int mapAwtKeyToVncKey(int key) {
- switch (key) {
- case KeyEvent.VK_BACK_SPACE:
- return 0xff08;
- case KeyEvent.VK_TAB:
- return 0xff09;
- case KeyEvent.VK_ENTER:
- return 0xff0d;
- case KeyEvent.VK_ESCAPE:
- return 0xff1b;
- case KeyEvent.VK_INSERT:
- return 0xff63;
- case KeyEvent.VK_DELETE:
- return 0xffff;
- case KeyEvent.VK_HOME:
- return 0xff50;
- case KeyEvent.VK_END:
- return 0xff57;
- case KeyEvent.VK_PAGE_UP:
- return 0xff55;
- case KeyEvent.VK_PAGE_DOWN:
- return 0xff56;
- case KeyEvent.VK_LEFT:
- return 0xff51;
- case KeyEvent.VK_UP:
- return 0xff52;
- case KeyEvent.VK_RIGHT:
- return 0xff53;
- case KeyEvent.VK_DOWN:
- return 0xff54;
- case KeyEvent.VK_F1:
- return 0xffbe;
- case KeyEvent.VK_F2:
- return 0xffbf;
- case KeyEvent.VK_F3:
- return 0xffc0;
- case KeyEvent.VK_F4:
- return 0xffc1;
- case KeyEvent.VK_F5:
- return 0xffc2;
- case KeyEvent.VK_F6:
- return 0xffc3;
- case KeyEvent.VK_F7:
- return 0xffc4;
- case KeyEvent.VK_F8:
- return 0xffc5;
- case KeyEvent.VK_F9:
- return 0xffc6;
- case KeyEvent.VK_F10:
- return 0xffc7;
- case KeyEvent.VK_F11:
- return 0xffc8;
- case KeyEvent.VK_F12:
- return 0xffc9;
- case KeyEvent.VK_SHIFT:
- return 0xffe1;
- case KeyEvent.VK_CONTROL:
- return 0xffe3;
- case KeyEvent.VK_META:
- return 0xffe7;
- case KeyEvent.VK_ALT:
- return 0xffe9;
- case KeyEvent.VK_ALT_GRAPH:
- return 0xffea;
- case KeyEvent.VK_BACK_QUOTE:
- return 0x0060;
}
- return key;
- }
+ private void sendSetEncodings() {
+ queue.add(new SetEncodingsPacket(RfbConstants.SUPPORTED_ENCODINGS_ARRAY));
+ }
+
+ private void sendSetPixelFormat() {
+ if (!screen.isRGB888_32_LE()) {
+ queue.add(new SetPixelFormatPacket(screen, 32, 24, RfbConstants.LITTLE_ENDIAN, RfbConstants.TRUE_COLOR, 255, 255, 255, 16, 8, 0));
+ }
+ }
+
+ public void closeConnection() {
+ connectionAlive = false;
+ }
+
+ public void requestFullScreenUpdate() {
+ queue.add(new FramebufferUpdateRequestPacket(RfbConstants.FRAMEBUFFER_FULL_UPDATE_REQUEST, 0, 0, screen.getFramebufferWidth(), screen.getFramebufferHeight()));
+ updateRequestSent = true;
+ }
+
+ @Override
+ public void imagePaintedOnScreen() {
+ if (!updateRequestSent) {
+ queue.add(new FramebufferUpdateRequestPacket(RfbConstants.FRAMEBUFFER_INCREMENTAL_UPDATE_REQUEST, 0, 0, screen.getFramebufferWidth(), screen.getFramebufferHeight()));
+ updateRequestSent = true;
+ }
+ }
+
+ @Override
+ public void frameBufferPacketReceived() {
+ updateRequestSent = false;
+ }
+
+ @Override
+ public void mouseDragged(MouseEvent e) {
+ queue.add(new MouseEventPacket(mapAwtModifiersToVncButtonMask(e.getModifiersEx()), e.getX(), e.getY()));
+ }
+
+ @Override
+ public void mouseMoved(MouseEvent e) {
+ queue.add(new MouseEventPacket(mapAwtModifiersToVncButtonMask(e.getModifiersEx()), e.getX(), e.getY()));
+ }
+
+ @Override
+ public void mouseClicked(MouseEvent e) {
+ // Nothing to do
+ }
+
+ @Override
+ public void mousePressed(MouseEvent e) {
+ queue.add(new MouseEventPacket(mapAwtModifiersToVncButtonMask(e.getModifiersEx()), e.getX(), e.getY()));
+ }
+
+ @Override
+ public void mouseReleased(MouseEvent e) {
+ queue.add(new MouseEventPacket(mapAwtModifiersToVncButtonMask(e.getModifiersEx()), e.getX(), e.getY()));
+ }
+
+ @Override
+ public void mouseEntered(MouseEvent e) {
+ // Nothing to do
+ }
+
+ @Override
+ public void mouseExited(MouseEvent e) {
+ // Nothing to do
+ }
+
+ /**
+ * Current state of buttons 1 to 8 are represented by bits 0 to 7 of
+ * button-mask respectively, 0 meaning up, 1 meaning down (pressed). On a
+ * conventional mouse, buttons 1, 2 and 3 correspond to the left, middle and
+ * right buttons on the mouse. On a wheel mouse, each step of the wheel
+ * upwards is represented by a press and release of button 4, and each step
+ * downwards is represented by a press and release of button 5.
+ *
+ * @param modifiers
+ * extended modifiers from AWT mouse event
+ * @return VNC mouse button mask
+ */
+ public static int mapAwtModifiersToVncButtonMask(int modifiers) {
+ int mask = (((modifiers & MouseEvent.BUTTON1_DOWN_MASK) != 0) ? 0x1 : 0) | (((modifiers & MouseEvent.BUTTON2_DOWN_MASK) != 0) ? 0x2 : 0)
+ | (((modifiers & MouseEvent.BUTTON3_DOWN_MASK) != 0) ? 0x4 : 0);
+ return mask;
+ }
+
+ @Override
+ public void keyTyped(KeyEvent e) {
+ // Do nothing
+ }
+
+ @Override
+ public void keyPressed(KeyEvent e) {
+ ClientPacket request = new KeyboardEventPacket(RfbConstants.KEY_DOWN, mapAwtKeyToVncKey(e.getKeyCode()));
+ queue.add(request);
+ }
+
+ @Override
+ public void keyReleased(KeyEvent e) {
+ ClientPacket request = new KeyboardEventPacket(RfbConstants.KEY_UP, mapAwtKeyToVncKey(e.getKeyCode()));
+ queue.add(request);
+ }
+
+ private int mapAwtKeyToVncKey(int key) {
+ switch (key) {
+ case KeyEvent.VK_BACK_SPACE:
+ return 0xff08;
+ case KeyEvent.VK_TAB:
+ return 0xff09;
+ case KeyEvent.VK_ENTER:
+ return 0xff0d;
+ case KeyEvent.VK_ESCAPE:
+ return 0xff1b;
+ case KeyEvent.VK_INSERT:
+ return 0xff63;
+ case KeyEvent.VK_DELETE:
+ return 0xffff;
+ case KeyEvent.VK_HOME:
+ return 0xff50;
+ case KeyEvent.VK_END:
+ return 0xff57;
+ case KeyEvent.VK_PAGE_UP:
+ return 0xff55;
+ case KeyEvent.VK_PAGE_DOWN:
+ return 0xff56;
+ case KeyEvent.VK_LEFT:
+ return 0xff51;
+ case KeyEvent.VK_UP:
+ return 0xff52;
+ case KeyEvent.VK_RIGHT:
+ return 0xff53;
+ case KeyEvent.VK_DOWN:
+ return 0xff54;
+ case KeyEvent.VK_F1:
+ return 0xffbe;
+ case KeyEvent.VK_F2:
+ return 0xffbf;
+ case KeyEvent.VK_F3:
+ return 0xffc0;
+ case KeyEvent.VK_F4:
+ return 0xffc1;
+ case KeyEvent.VK_F5:
+ return 0xffc2;
+ case KeyEvent.VK_F6:
+ return 0xffc3;
+ case KeyEvent.VK_F7:
+ return 0xffc4;
+ case KeyEvent.VK_F8:
+ return 0xffc5;
+ case KeyEvent.VK_F9:
+ return 0xffc6;
+ case KeyEvent.VK_F10:
+ return 0xffc7;
+ case KeyEvent.VK_F11:
+ return 0xffc8;
+ case KeyEvent.VK_F12:
+ return 0xffc9;
+ case KeyEvent.VK_SHIFT:
+ return 0xffe1;
+ case KeyEvent.VK_CONTROL:
+ return 0xffe3;
+ case KeyEvent.VK_META:
+ return 0xffe7;
+ case KeyEvent.VK_ALT:
+ return 0xffe9;
+ case KeyEvent.VK_ALT_GRAPH:
+ return 0xffea;
+ case KeyEvent.VK_BACK_QUOTE:
+ return 0x0060;
+ }
+
+ return key;
+ }
}
diff --git a/console-proxy/src/com/cloud/consoleproxy/vnc/VncScreenDescription.java b/console-proxy/src/com/cloud/consoleproxy/vnc/VncScreenDescription.java
index c9e135ecd34..44b2a34769b 100644
--- a/console-proxy/src/com/cloud/consoleproxy/vnc/VncScreenDescription.java
+++ b/console-proxy/src/com/cloud/consoleproxy/vnc/VncScreenDescription.java
@@ -21,70 +21,69 @@ package com.cloud.consoleproxy.vnc;
*/
public class VncScreenDescription {
- // Frame buffer size
- private int framebufferWidth = -1;
- private int framebufferHeight = -1;
+ // Frame buffer size
+ private int framebufferWidth = -1;
+ private int framebufferHeight = -1;
- // Desktop name
- private String desktopName;
+ // Desktop name
+ private String desktopName;
- // Bytes per pixel
- private int bytesPerPixel;
+ // Bytes per pixel
+ private int bytesPerPixel;
- // Indicates that screen uses format which we want to use:
- // RGB 24bit packed into 32bit little-endian int.
- private boolean rgb888_32_le = false;
+ // Indicates that screen uses format which we want to use:
+ // RGB 24bit packed into 32bit little-endian int.
+ private boolean rgb888_32_le = false;
- public VncScreenDescription() {
- }
+ public VncScreenDescription() {
+ }
- /**
- * Store information about server pixel format.
- */
- public void setPixelFormat(int bitsPerPixel, int depth, int bigEndianFlag, int trueColorFlag, int redMax, int greenMax, int blueMax, int redShift,
- int greenShift, int blueShift) {
+ /**
+ * Store information about server pixel format.
+ */
+ public void setPixelFormat(int bitsPerPixel, int depth, int bigEndianFlag, int trueColorFlag, int redMax, int greenMax, int blueMax, int redShift, int greenShift, int blueShift) {
- bytesPerPixel = (bitsPerPixel + 7) / 8;
+ bytesPerPixel = (bitsPerPixel + 7) / 8;
- rgb888_32_le = (depth == 24 && bitsPerPixel == 32 && redShift == 16 && greenShift == 8 && blueShift == 0 && redMax == 255 && greenMax == 255
- && blueMax == 255 && bigEndianFlag == RfbConstants.LITTLE_ENDIAN && trueColorFlag == RfbConstants.TRUE_COLOR);
- }
+ rgb888_32_le = (depth == 24 && bitsPerPixel == 32 && redShift == 16 && greenShift == 8 && blueShift == 0 && redMax == 255 && greenMax == 255 && blueMax == 255
+ && bigEndianFlag == RfbConstants.LITTLE_ENDIAN && trueColorFlag == RfbConstants.TRUE_COLOR);
+ }
- /**
- * Store information about server screen size.
- */
- public void setFramebufferSize(int framebufferWidth, int framebufferHeight) {
- this.framebufferWidth = framebufferWidth;
- this.framebufferHeight = framebufferHeight;
- }
+ /**
+ * Store information about server screen size.
+ */
+ public void setFramebufferSize(int framebufferWidth, int framebufferHeight) {
+ this.framebufferWidth = framebufferWidth;
+ this.framebufferHeight = framebufferHeight;
+ }
- /**
- * Store server desktop name.
- */
- public void setDesktopName(String desktopName) {
- this.desktopName = desktopName;
- }
+ /**
+ * Store server desktop name.
+ */
+ public void setDesktopName(String desktopName) {
+ this.desktopName = desktopName;
+ }
- // Getters for variables, as usual
+ // Getters for variables, as usual
- public String getDesktopName() {
- return desktopName;
- }
+ public String getDesktopName() {
+ return desktopName;
+ }
- public int getBytesPerPixel() {
- return bytesPerPixel;
- }
+ public int getBytesPerPixel() {
+ return bytesPerPixel;
+ }
- public int getFramebufferHeight() {
- return framebufferHeight;
- }
+ public int getFramebufferHeight() {
+ return framebufferHeight;
+ }
- public int getFramebufferWidth() {
- return framebufferWidth;
- }
+ public int getFramebufferWidth() {
+ return framebufferWidth;
+ }
- public boolean isRGB888_32_LE() {
- return rgb888_32_le;
- }
+ public boolean isRGB888_32_LE() {
+ return rgb888_32_le;
+ }
}
diff --git a/console-proxy/src/com/cloud/consoleproxy/vnc/VncServerPacketReceiver.java b/console-proxy/src/com/cloud/consoleproxy/vnc/VncServerPacketReceiver.java
index 06a4f0332e3..57c8ff8efe2 100644
--- a/console-proxy/src/com/cloud/consoleproxy/vnc/VncServerPacketReceiver.java
+++ b/console-proxy/src/com/cloud/consoleproxy/vnc/VncServerPacketReceiver.java
@@ -27,97 +27,97 @@ import com.cloud.consoleproxy.vnc.packet.server.FramebufferUpdatePacket;
import com.cloud.consoleproxy.vnc.packet.server.ServerCutText;
public class VncServerPacketReceiver implements Runnable {
- private static final Logger s_logger = Logger.getLogger(VncServerPacketReceiver.class);
+ private static final Logger s_logger = Logger.getLogger(VncServerPacketReceiver.class);
- private final VncScreenDescription screen;
- private BufferedImageCanvas canvas;
- private DataInputStream is;
+ private final VncScreenDescription screen;
+ private BufferedImageCanvas canvas;
+ private DataInputStream is;
- private boolean connectionAlive = true;
- private VncClient vncConnection;
- private final FrameBufferUpdateListener fburListener;
- private final ConsoleProxyClientListener clientListener;
+ private boolean connectionAlive = true;
+ private VncClient vncConnection;
+ private final FrameBufferUpdateListener fburListener;
+ private final ConsoleProxyClientListener clientListener;
- public VncServerPacketReceiver(DataInputStream is, BufferedImageCanvas canvas, VncScreenDescription screen, VncClient vncConnection,
- FrameBufferUpdateListener fburListener, ConsoleProxyClientListener clientListener) {
- this.screen = screen;
- this.canvas = canvas;
- this.is = is;
- this.vncConnection = vncConnection;
- this.fburListener = fburListener;
- this.clientListener = clientListener;
- }
-
- public BufferedImageCanvas getCanvas() {
- return canvas;
- }
-
- @Override
- public void run() {
- try {
- while (connectionAlive) {
-
- // Read server message type
- int messageType = is.readUnsignedByte();
-
- // Invoke packet handler by packet type.
- switch (messageType) {
-
- case RfbConstants.SERVER_FRAMEBUFFER_UPDATE: {
- // Notify sender that frame buffer update is received,
- // so it can send another frame buffer update request
- fburListener.frameBufferPacketReceived();
- // Handle frame buffer update
- new FramebufferUpdatePacket(canvas, screen, is, clientListener);
- break;
- }
-
- case RfbConstants.SERVER_BELL: {
- serverBell();
- break;
- }
-
- case RfbConstants.SERVER_CUT_TEXT: {
- serverCutText(is);
- break;
- }
-
- default:
- throw new RuntimeException("Unknown server packet type: " + messageType + ".");
- }
- }
- } catch (Throwable e) {
- s_logger.error("Unexpected exception: ", e);
- if (connectionAlive) {
- closeConnection();
- vncConnection.shutdown();
- }
+ public VncServerPacketReceiver(DataInputStream is, BufferedImageCanvas canvas, VncScreenDescription screen, VncClient vncConnection, FrameBufferUpdateListener fburListener,
+ ConsoleProxyClientListener clientListener) {
+ this.screen = screen;
+ this.canvas = canvas;
+ this.is = is;
+ this.vncConnection = vncConnection;
+ this.fburListener = fburListener;
+ this.clientListener = clientListener;
}
- }
- public void closeConnection() {
- connectionAlive = false;
- }
-
- public boolean isConnectionAlive() {
- return connectionAlive;
- }
+ public BufferedImageCanvas getCanvas() {
+ return canvas;
+ }
- /**
- * Handle server bell packet.
- */
- private void serverBell() {
- Toolkit.getDefaultToolkit().beep();
- }
+ @Override
+ public void run() {
+ try {
+ while (connectionAlive) {
- /**
- * Handle packet with server clip-board.
- */
- private void serverCutText(DataInputStream is) throws IOException {
- ServerCutText clipboardContent = new ServerCutText(is);
- StringSelection contents = new StringSelection(clipboardContent.getContent());
- Toolkit.getDefaultToolkit().getSystemClipboard().setContents(contents, null);
-
- s_logger.info("Server clipboard buffer: "+clipboardContent.getContent());
- }
+ // Read server message type
+ int messageType = is.readUnsignedByte();
+
+ // Invoke packet handler by packet type.
+ switch (messageType) {
+
+ case RfbConstants.SERVER_FRAMEBUFFER_UPDATE: {
+ // Notify sender that frame buffer update is received,
+ // so it can send another frame buffer update request
+ fburListener.frameBufferPacketReceived();
+ // Handle frame buffer update
+ new FramebufferUpdatePacket(canvas, screen, is, clientListener);
+ break;
+ }
+
+ case RfbConstants.SERVER_BELL: {
+ serverBell();
+ break;
+ }
+
+ case RfbConstants.SERVER_CUT_TEXT: {
+ serverCutText(is);
+ break;
+ }
+
+ default:
+ throw new RuntimeException("Unknown server packet type: " + messageType + ".");
+ }
+ }
+ } catch (Throwable e) {
+ s_logger.error("Unexpected exception: ", e);
+ if (connectionAlive) {
+ closeConnection();
+ vncConnection.shutdown();
+ }
+ }
+ }
+
+ public void closeConnection() {
+ connectionAlive = false;
+ }
+
+ public boolean isConnectionAlive() {
+ return connectionAlive;
+ }
+
+ /**
+ * Handle server bell packet.
+ */
+ private void serverBell() {
+ Toolkit.getDefaultToolkit().beep();
+ }
+
+ /**
+ * Handle packet with server clip-board.
+ */
+ private void serverCutText(DataInputStream is) throws IOException {
+ ServerCutText clipboardContent = new ServerCutText(is);
+ StringSelection contents = new StringSelection(clipboardContent.getContent());
+ Toolkit.getDefaultToolkit().getSystemClipboard().setContents(contents, null);
+
+ s_logger.info("Server clipboard buffer: " + clipboardContent.getContent());
+ }
}
diff --git a/console-proxy/src/com/cloud/consoleproxy/vnc/packet/client/ClientPacket.java b/console-proxy/src/com/cloud/consoleproxy/vnc/packet/client/ClientPacket.java
index 10e7c021cb1..873b8c0825e 100644
--- a/console-proxy/src/com/cloud/consoleproxy/vnc/packet/client/ClientPacket.java
+++ b/console-proxy/src/com/cloud/consoleproxy/vnc/packet/client/ClientPacket.java
@@ -21,6 +21,6 @@ import java.io.IOException;
public interface ClientPacket {
- void write(DataOutputStream os) throws IOException;
+ void write(DataOutputStream os) throws IOException;
}
diff --git a/console-proxy/src/com/cloud/consoleproxy/vnc/packet/client/FramebufferUpdateRequestPacket.java b/console-proxy/src/com/cloud/consoleproxy/vnc/packet/client/FramebufferUpdateRequestPacket.java
index b5e87a88f57..d3a6e40e961 100644
--- a/console-proxy/src/com/cloud/consoleproxy/vnc/packet/client/FramebufferUpdateRequestPacket.java
+++ b/console-proxy/src/com/cloud/consoleproxy/vnc/packet/client/FramebufferUpdateRequestPacket.java
@@ -28,27 +28,26 @@ import com.cloud.consoleproxy.vnc.RfbConstants;
*/
public class FramebufferUpdateRequestPacket implements ClientPacket {
- private final int incremental;
- private final int x, y, width, height;
+ private final int incremental;
+ private final int x, y, width, height;
- public FramebufferUpdateRequestPacket(int incremental, int x, int y, int width, int height) {
- this.incremental = incremental;
- this.x = x;
- this.y = y;
- this.width = width;
- this.height = height;
- }
+ public FramebufferUpdateRequestPacket(int incremental, int x, int y, int width, int height) {
+ this.incremental = incremental;
+ this.x = x;
+ this.y = y;
+ this.width = width;
+ this.height = height;
+ }
+ @Override
+ public void write(DataOutputStream os) throws IOException {
+ os.writeByte(RfbConstants.CLIENT_FRAMEBUFFER_UPDATE_REQUEST);
- @Override
- public void write(DataOutputStream os) throws IOException {
- os.writeByte(RfbConstants.CLIENT_FRAMEBUFFER_UPDATE_REQUEST);
-
- os.writeByte(incremental);
- os.writeShort(x);
- os.writeShort(y);
- os.writeShort(width);
- os.writeShort(height);
- }
+ os.writeByte(incremental);
+ os.writeShort(x);
+ os.writeShort(y);
+ os.writeShort(width);
+ os.writeShort(height);
+ }
}
diff --git a/console-proxy/src/com/cloud/consoleproxy/vnc/packet/client/KeyboardEventPacket.java b/console-proxy/src/com/cloud/consoleproxy/vnc/packet/client/KeyboardEventPacket.java
index 335fee6b176..8efbab123a5 100644
--- a/console-proxy/src/com/cloud/consoleproxy/vnc/packet/client/KeyboardEventPacket.java
+++ b/console-proxy/src/com/cloud/consoleproxy/vnc/packet/client/KeyboardEventPacket.java
@@ -23,20 +23,20 @@ import com.cloud.consoleproxy.vnc.RfbConstants;
public class KeyboardEventPacket implements ClientPacket {
- private final int downFlag, key;
-
- public KeyboardEventPacket(int downFlag, int key) {
- this.downFlag = downFlag;
- this.key = key;
- }
+ private final int downFlag, key;
- @Override
- public void write(DataOutputStream os) throws IOException {
- os.writeByte(RfbConstants.CLIENT_KEYBOARD_EVENT);
+ public KeyboardEventPacket(int downFlag, int key) {
+ this.downFlag = downFlag;
+ this.key = key;
+ }
- os.writeByte(downFlag);
- os.writeShort(0); // padding
- os.writeInt(key);
- }
+ @Override
+ public void write(DataOutputStream os) throws IOException {
+ os.writeByte(RfbConstants.CLIENT_KEYBOARD_EVENT);
+
+ os.writeByte(downFlag);
+ os.writeShort(0); // padding
+ os.writeInt(key);
+ }
}
diff --git a/console-proxy/src/com/cloud/consoleproxy/vnc/packet/client/MouseEventPacket.java b/console-proxy/src/com/cloud/consoleproxy/vnc/packet/client/MouseEventPacket.java
index 4b799f6f2f7..b42191cbadc 100644
--- a/console-proxy/src/com/cloud/consoleproxy/vnc/packet/client/MouseEventPacket.java
+++ b/console-proxy/src/com/cloud/consoleproxy/vnc/packet/client/MouseEventPacket.java
@@ -23,21 +23,21 @@ import com.cloud.consoleproxy.vnc.RfbConstants;
public class MouseEventPacket implements ClientPacket {
- private final int buttonMask, x, y;
+ private final int buttonMask, x, y;
- public MouseEventPacket(int buttonMask, int x, int y) {
- this.buttonMask = buttonMask;
- this.x = x;
- this.y = y;
- }
+ public MouseEventPacket(int buttonMask, int x, int y) {
+ this.buttonMask = buttonMask;
+ this.x = x;
+ this.y = y;
+ }
- @Override
- public void write(DataOutputStream os) throws IOException {
- os.writeByte(RfbConstants.CLIENT_POINTER_EVENT);
+ @Override
+ public void write(DataOutputStream os) throws IOException {
+ os.writeByte(RfbConstants.CLIENT_POINTER_EVENT);
- os.writeByte(buttonMask);
- os.writeShort(x);
- os.writeShort(y);
- }
+ os.writeByte(buttonMask);
+ os.writeShort(x);
+ os.writeShort(y);
+ }
}
diff --git a/console-proxy/src/com/cloud/consoleproxy/vnc/packet/client/SetEncodingsPacket.java b/console-proxy/src/com/cloud/consoleproxy/vnc/packet/client/SetEncodingsPacket.java
index f34576f23f0..3d8cfcb09a6 100644
--- a/console-proxy/src/com/cloud/consoleproxy/vnc/packet/client/SetEncodingsPacket.java
+++ b/console-proxy/src/com/cloud/consoleproxy/vnc/packet/client/SetEncodingsPacket.java
@@ -23,26 +23,23 @@ import com.cloud.consoleproxy.vnc.RfbConstants;
public class SetEncodingsPacket implements ClientPacket {
- private final int[] encodings;
+ private final int[] encodings;
- public SetEncodingsPacket(int[] encodings)
- {
- this.encodings = encodings;
- }
-
- @Override
- public void write(DataOutputStream os) throws IOException
- {
- os.writeByte(RfbConstants.CLIENT_SET_ENCODINGS);
-
- os.writeByte(0);//padding
-
- os.writeShort(encodings.length);
-
- for(int i=0;i
-tileMap = [ ${tileSequence} ];
-<#if resized == true>
- ajaxViewer.resize('main_panel', ${width}, ${height}, ${tileWidth}, ${tileHeight});
-#if>
-ajaxViewer.refresh('${imgUrl}', tileMap, false);
-
+<#--
+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.
+-->
+tileMap = [ ${tileSequence} ];
+<#if resized == true>
+ ajaxViewer.resize('main_panel', ${width}, ${height}, ${tileWidth}, ${tileHeight});
+#if>
+ajaxViewer.refresh('${imgUrl}', tileMap, false);
+