You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cloudstack.apache.org by mi...@apache.org on 2012/08/13 09:35:57 UTC

[2/8] git commit: Remove @author tag from non third-party source files in console-proxy folder and repalce tab indention with 4 spaces

Remove @author tag from non third-party source files in console-proxy folder and repalce tab indention with 4 spaces


Project: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/commit/b25122bd
Tree: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/tree/b25122bd
Diff: http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/diff/b25122bd

Branch: refs/heads/master
Commit: b25122bd4de1c5564e1fe1018747a72da1e634c5
Parents: 89015cb
Author: Mice Xia <mi...@apache.org>
Authored: Mon Aug 13 15:26:03 2012 +0800
Committer: Mice Xia <mi...@apache.org>
Committed: Mon Aug 13 15:26:03 2012 +0800

----------------------------------------------------------------------
 .../src/com/cloud/consoleproxy/ConsoleProxy.java   |  957 +++++++--------
 .../com/cloud/consoleproxy/ConsoleProxyClient.java |  107 +-
 .../cloud/consoleproxy/ConsoleProxyClientBase.java |  876 +++++++-------
 .../consoleproxy/ConsoleProxyClientParam.java      |  189 ++--
 .../ConsoleProxyClientStatsCollector.java          |  145 ++--
 .../cloud/consoleproxy/ConsoleProxyGCThread.java   |  183 ++--
 .../ConsoleProxyPasswordBasedEncryptor.java        |  253 ++--
 .../cloud/consoleproxy/ConsoleProxyVncClient.java  |  429 ++++----
 8 files changed, 1565 insertions(+), 1574 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/b25122bd/console-proxy/src/com/cloud/consoleproxy/ConsoleProxy.java
----------------------------------------------------------------------
diff --git a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxy.java b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxy.java
index 94f1ef0..9f1304f 100644
--- a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxy.java
+++ b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxy.java
@@ -14,487 +14,486 @@
 // 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.InputStream;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
-import java.net.InetSocketAddress;
-import java.net.URISyntaxException;
-import java.net.URL;
+package com.cloud.consoleproxy;
+
+import java.io.File;
+import java.io.InputStream;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.InetSocketAddress;
+import java.net.URISyntaxException;
+import java.net.URL;
 import java.security.NoSuchAlgorithmException;
 import java.security.SecureRandom;
-import java.util.Hashtable;
-import java.util.Map;
-import java.util.Properties;
-import java.util.concurrent.Executor;
-
+import java.util.Hashtable;
+import java.util.Map;
+import java.util.Properties;
+import java.util.concurrent.Executor;
+
 import org.apache.axis.encoding.Base64;
-import org.apache.log4j.xml.DOMConfigurator;
-
-import com.cloud.consoleproxy.util.Logger;
+import org.apache.log4j.xml.DOMConfigurator;
+
+import com.cloud.consoleproxy.util.Logger;
 import com.google.gson.Gson;
-import com.sun.net.httpserver.HttpServer;
-
-/**
- * 
- * @author Kelven Yang
- * ConsoleProxy, singleton class that manages overall activities in console proxy process. To make legacy code work, we still
- */
-public class ConsoleProxy {
-	private static final Logger s_logger = Logger.getLogger(ConsoleProxy.class);
-	
-	public static final int KEYBOARD_RAW = 0;
-	public static final int KEYBOARD_COOKED = 1;
-	
-	public static int VIEWER_LINGER_SECONDS = 180;
-	
-	public static Object context;
-	
-	// this has become more ugly, to store keystore info passed from management server (we now use management server managed keystore to support
-	// dynamically changing to customer supplied certificate)
-	public static byte[] ksBits;
-	public static String ksPassword;
-	
-	public static Method authMethod;
-	public static Method reportMethod;
-	public static Method ensureRouteMethod;
-	
-	static Hashtable<String, ConsoleProxyClient> connectionMap = new Hashtable<String, ConsoleProxyClient>();
-	static int httpListenPort = 80;
-	static int httpCmdListenPort = 8001;
-	static int reconnectMaxRetry = 5;
-	static int readTimeoutSeconds = 90;
-	static int keyboardType = KEYBOARD_RAW;
-	static String factoryClzName;
-	static boolean standaloneStart = false;
-	
-	static String encryptorPassword = genDefaultEncryptorPassword(); 
-	
-	private static String genDefaultEncryptorPassword() {
-		try {
-			SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
-			
-			byte[] randomBytes = new byte[16];
-			random.nextBytes(randomBytes);
-			return Base64.encode(randomBytes);
-		} catch (NoSuchAlgorithmException e) {
-			s_logger.error("Unexpected exception ", e);
-			assert(false);
-		}
-		
-		return "Dummy";
-	}
-	
-	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");
-			}
-			// DOMConfigurator.configure(configUrl);
-		} else {
-			System.out.println("Configure log4j with default properties");
-		}
-	}
-	
-	private static void configProxy(Properties conf) {
-		s_logger.info("Configure console proxy...");
-		for(Object key : conf.keySet()) {
-			s_logger.info("Property " + (String)key + ": " + conf.getProperty((String)key));
-		}
-		
-		String s = conf.getProperty("consoleproxy.httpListenPort");
-		if (s!=null) {
-			httpListenPort = Integer.parseInt(s);
-			s_logger.info("Setting httpListenPort=" + s);
-		}
-		
-		s = conf.getProperty("premium");
-		if(s != null && s.equalsIgnoreCase("true")) {
-			s_logger.info("Premium setting will override settings from consoleproxy.properties, listen at port 443");
-			httpListenPort = 443;
-			factoryClzName = "com.cloud.consoleproxy.ConsoleProxySecureServerFactoryImpl";
-		} else {
-			factoryClzName = ConsoleProxyBaseServerFactoryImpl.class.getName();
-		}
-		
-		s = conf.getProperty("consoleproxy.httpCmdListenPort");
-		if (s!=null) {
-			httpCmdListenPort = Integer.parseInt(s);
-			s_logger.info("Setting httpCmdListenPort=" + s);
-		}
-		
-		s = conf.getProperty("consoleproxy.reconnectMaxRetry");
-		if (s!=null) {
-			reconnectMaxRetry = Integer.parseInt(s);
-			s_logger.info("Setting reconnectMaxRetry=" + reconnectMaxRetry);
-		}
-		
-		s = conf.getProperty("consoleproxy.readTimeoutSeconds");
-		if (s!=null) {
-			readTimeoutSeconds = Integer.parseInt(s);
-			s_logger.info("Setting readTimeoutSeconds=" + readTimeoutSeconds);
-		}
-	}
-	
-	public static ConsoleProxyServerFactory getHttpServerFactory() {
-		try {
-			Class<?> clz = Class.forName(factoryClzName);
-			try {
-				ConsoleProxyServerFactory factory = (ConsoleProxyServerFactory)clz.newInstance();
-				factory.init(ConsoleProxy.ksBits, ConsoleProxy.ksPassword);
-				return factory;
-			} catch (InstantiationException e) {
-				s_logger.error(e.getMessage(), e);
-				return null;
-			} catch (IllegalAccessException e) {
-				s_logger.error(e.getMessage(), e);
-				return null;
-			}
-		} catch (ClassNotFoundException e) {
-			s_logger.warn("Unable to find http server factory class: " + factoryClzName);
-			return new ConsoleProxyBaseServerFactoryImpl();
-		}
-	}
-
-	public static ConsoleProxyAuthenticationResult authenticateConsoleAccess(ConsoleProxyClientParam param, boolean reauthentication) {
+import com.sun.net.httpserver.HttpServer;
+
+/**
+ * 
+ * ConsoleProxy, singleton class that manages overall activities in console proxy process. To make legacy code work, we still
+ */
+public class ConsoleProxy {
+    private static final Logger s_logger = Logger.getLogger(ConsoleProxy.class);
+    
+    public static final int KEYBOARD_RAW = 0;
+    public static final int KEYBOARD_COOKED = 1;
+    
+    public static int VIEWER_LINGER_SECONDS = 180;
+    
+    public static Object context;
+    
+    // this has become more ugly, to store keystore info passed from management server (we now use management server managed keystore to support
+    // dynamically changing to customer supplied certificate)
+    public static byte[] ksBits;
+    public static String ksPassword;
+    
+    public static Method authMethod;
+    public static Method reportMethod;
+    public static Method ensureRouteMethod;
+    
+    static Hashtable<String, ConsoleProxyClient> connectionMap = new Hashtable<String, ConsoleProxyClient>();
+    static int httpListenPort = 80;
+    static int httpCmdListenPort = 8001;
+    static int reconnectMaxRetry = 5;
+    static int readTimeoutSeconds = 90;
+    static int keyboardType = KEYBOARD_RAW;
+    static String factoryClzName;
+    static boolean standaloneStart = false;
+    
+    static String encryptorPassword = genDefaultEncryptorPassword(); 
+    
+    private static String genDefaultEncryptorPassword() {
+        try {
+            SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
+            
+            byte[] randomBytes = new byte[16];
+            random.nextBytes(randomBytes);
+            return Base64.encode(randomBytes);
+        } catch (NoSuchAlgorithmException e) {
+            s_logger.error("Unexpected exception ", e);
+            assert(false);
+        }
+        
+        return "Dummy";
+    }
+    
+    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");
+            }
+            // DOMConfigurator.configure(configUrl);
+        } else {
+            System.out.println("Configure log4j with default properties");
+        }
+    }
+    
+    private static void configProxy(Properties conf) {
+        s_logger.info("Configure console proxy...");
+        for(Object key : conf.keySet()) {
+            s_logger.info("Property " + (String)key + ": " + conf.getProperty((String)key));
+        }
+        
+        String s = conf.getProperty("consoleproxy.httpListenPort");
+        if (s!=null) {
+            httpListenPort = Integer.parseInt(s);
+            s_logger.info("Setting httpListenPort=" + s);
+        }
+        
+        s = conf.getProperty("premium");
+        if(s != null && s.equalsIgnoreCase("true")) {
+            s_logger.info("Premium setting will override settings from consoleproxy.properties, listen at port 443");
+            httpListenPort = 443;
+            factoryClzName = "com.cloud.consoleproxy.ConsoleProxySecureServerFactoryImpl";
+        } else {
+            factoryClzName = ConsoleProxyBaseServerFactoryImpl.class.getName();
+        }
+        
+        s = conf.getProperty("consoleproxy.httpCmdListenPort");
+        if (s!=null) {
+            httpCmdListenPort = Integer.parseInt(s);
+            s_logger.info("Setting httpCmdListenPort=" + s);
+        }
+        
+        s = conf.getProperty("consoleproxy.reconnectMaxRetry");
+        if (s!=null) {
+            reconnectMaxRetry = Integer.parseInt(s);
+            s_logger.info("Setting reconnectMaxRetry=" + reconnectMaxRetry);
+        }
+        
+        s = conf.getProperty("consoleproxy.readTimeoutSeconds");
+        if (s!=null) {
+            readTimeoutSeconds = Integer.parseInt(s);
+            s_logger.info("Setting readTimeoutSeconds=" + readTimeoutSeconds);
+        }
+    }
+    
+    public static ConsoleProxyServerFactory getHttpServerFactory() {
+        try {
+            Class<?> clz = Class.forName(factoryClzName);
+            try {
+                ConsoleProxyServerFactory factory = (ConsoleProxyServerFactory)clz.newInstance();
+                factory.init(ConsoleProxy.ksBits, ConsoleProxy.ksPassword);
+                return factory;
+            } catch (InstantiationException e) {
+                s_logger.error(e.getMessage(), e);
+                return null;
+            } catch (IllegalAccessException e) {
+                s_logger.error(e.getMessage(), e);
+                return null;
+            }
+        } catch (ClassNotFoundException e) {
+            s_logger.warn("Unable to find http server factory class: " + factoryClzName);
+            return new ConsoleProxyBaseServerFactoryImpl();
+        }
+    }
+
+    public static ConsoleProxyAuthenticationResult authenticateConsoleAccess(ConsoleProxyClientParam param, boolean reauthentication) {
+
+        ConsoleProxyAuthenticationResult authResult = new ConsoleProxyAuthenticationResult();
+        authResult.setSuccess(true);
+        authResult.setReauthentication(reauthentication);
+        authResult.setHost(param.getClientHostAddress());
+        authResult.setPort(param.getClientHostPort());
+        
+        if(standaloneStart) {
+            return authResult;
+        }
+        
+        if(authMethod != null) {
+            Object result;
+            try {
+                result = authMethod.invoke(ConsoleProxy.context, 
+                    param.getClientHostAddress(), 
+                    String.valueOf(param.getClientHostPort()), 
+                    param.getClientTag(), 
+                    param.getClientHostPassword(), 
+                    param.getTicket(),
+                    new Boolean(reauthentication));
+            } catch (IllegalAccessException e) {
+                s_logger.error("Unable to invoke authenticateConsoleAccess due to IllegalAccessException" + " for vm: " + param.getClientTag(), e);
+                authResult.setSuccess(false);
+                return authResult;
+            } catch (InvocationTargetException e) {
+                s_logger.error("Unable to invoke authenticateConsoleAccess due to InvocationTargetException " + " for vm: " + param.getClientTag(), e);
+                authResult.setSuccess(false);
+                return authResult;
+            }
+            
+            if(result != null && result instanceof String) {
+                authResult = new Gson().fromJson((String)result, ConsoleProxyAuthenticationResult.class);
+            } else {
+                s_logger.error("Invalid authentication return object " + result + " for vm: " + param.getClientTag() + ", decline the access");
+                authResult.setSuccess(false);
+            }
+        } else {
+            s_logger.warn("Private channel towards management server is not setup. Switch to offline mode and allow access to vm: " + param.getClientTag());
+        }
+        
+        return authResult;
+    }
+    
+    public static void reportLoadInfo(String gsonLoadInfo) {
+        if(reportMethod != null) {
+            try {
+                reportMethod.invoke(ConsoleProxy.context, gsonLoadInfo);
+            } catch (IllegalAccessException e) {
+                s_logger.error("Unable to invoke reportLoadInfo due to " + e.getMessage());
+            } catch (InvocationTargetException e) {
+                s_logger.error("Unable to invoke reportLoadInfo due to " + e.getMessage());
+            }
+        } else {
+            s_logger.warn("Private channel towards management server is not setup. Switch to offline mode and ignore load report");
+        }
+    }
+    
+    public static void ensureRoute(String address) {
+        if(ensureRouteMethod != null) {
+            try {
+                ensureRouteMethod.invoke(ConsoleProxy.context, address);
+            } catch (IllegalAccessException e) {
+                s_logger.error("Unable to invoke ensureRoute due to " + e.getMessage());
+            } catch (InvocationTargetException e) {
+                s_logger.error("Unable to invoke ensureRoute due to " + e.getMessage());
+            }
+        } else {
+            s_logger.warn("Unable to find ensureRoute method, console proxy agent is not up to date");
+        }
+    }
+
+    public static void startWithContext(Properties conf, Object context, byte[] ksBits, String ksPassword) {
+        s_logger.info("Start console proxy with context");
+        if(conf != null) {
+            for(Object key : conf.keySet()) {
+                s_logger.info("Context property " + (String)key + ": " + conf.getProperty((String)key));
+            }
+        }
+        
+        configLog4j();
+        Logger.setFactory(new ConsoleProxyLoggerFactory());
+        
+        // Using reflection to setup private/secure communication channel towards management server
+        ConsoleProxy.context = context;
+        ConsoleProxy.ksBits = ksBits;
+        ConsoleProxy.ksPassword = ksPassword;
+        try {
+            Class<?> contextClazz = Class.forName("com.cloud.agent.resource.consoleproxy.ConsoleProxyResource");
+            authMethod = contextClazz.getDeclaredMethod("authenticateConsoleAccess", String.class, String.class, String.class, String.class, String.class, Boolean.class);
+            reportMethod = contextClazz.getDeclaredMethod("reportLoadInfo", String.class);
+            ensureRouteMethod = contextClazz.getDeclaredMethod("ensureRoute", String.class);
+        } catch (SecurityException e) {
+            s_logger.error("Unable to setup private channel due to SecurityException", e);
+        } catch (NoSuchMethodException e) {
+            s_logger.error("Unable to setup private channel due to NoSuchMethodException", e);
+        } catch (IllegalArgumentException e) {
+            s_logger.error("Unable to setup private channel due to IllegalArgumentException", e);
+        } catch(ClassNotFoundException e) {
+            s_logger.error("Unable to setup private channel due to ClassNotFoundException", e);
+        }
+        
+        // merge properties from conf file
+        InputStream confs = ConsoleProxy.class.getResourceAsStream("/conf/consoleproxy.properties");
+        Properties props = new Properties();
+        if (confs == null) {
+            s_logger.info("Can't load consoleproxy.properties from classpath, will use default configuration");
+        } else {
+            try {
+                props.load(confs);
+                
+                for(Object key : props.keySet()) {
+                    // give properties passed via context high priority, treat properties from consoleproxy.properties
+                    // as default values
+                    if(conf.get(key) == null)
+                        conf.put(key, props.get(key));
+                }
+            }  catch (Exception e) {
+                s_logger.error(e.toString(), e);
+            }
+        }
+        
+        start(conf);
+    }
 
-		ConsoleProxyAuthenticationResult authResult = new ConsoleProxyAuthenticationResult();
-		authResult.setSuccess(true);
-		authResult.setReauthentication(reauthentication);
-		authResult.setHost(param.getClientHostAddress());
-		authResult.setPort(param.getClientHostPort());
-		
-		if(standaloneStart) {
-			return authResult;
-		}
-		
-		if(authMethod != null) {
-			Object result;
-			try {
-				result = authMethod.invoke(ConsoleProxy.context, 
-					param.getClientHostAddress(), 
-					String.valueOf(param.getClientHostPort()), 
-					param.getClientTag(), 
-					param.getClientHostPassword(), 
-					param.getTicket(),
-					new Boolean(reauthentication));
-			} catch (IllegalAccessException e) {
-				s_logger.error("Unable to invoke authenticateConsoleAccess due to IllegalAccessException" + " for vm: " + param.getClientTag(), e);
-				authResult.setSuccess(false);
-				return authResult;
-			} catch (InvocationTargetException e) {
-				s_logger.error("Unable to invoke authenticateConsoleAccess due to InvocationTargetException " + " for vm: " + param.getClientTag(), e);
-				authResult.setSuccess(false);
-				return authResult;
-			}
-			
-			if(result != null && result instanceof String) {
-				authResult = new Gson().fromJson((String)result, ConsoleProxyAuthenticationResult.class);
-			} else {
-				s_logger.error("Invalid authentication return object " + result + " for vm: " + param.getClientTag() + ", decline the access");
-				authResult.setSuccess(false);
-			}
-		} else {
-			s_logger.warn("Private channel towards management server is not setup. Switch to offline mode and allow access to vm: " + param.getClientTag());
-		}
-		
-		return authResult;
-	}
-	
-	public static void reportLoadInfo(String gsonLoadInfo) {
-		if(reportMethod != null) {
-			try {
-				reportMethod.invoke(ConsoleProxy.context, gsonLoadInfo);
-			} catch (IllegalAccessException e) {
-				s_logger.error("Unable to invoke reportLoadInfo due to " + e.getMessage());
-			} catch (InvocationTargetException e) {
-				s_logger.error("Unable to invoke reportLoadInfo due to " + e.getMessage());
-			}
-		} else {
-			s_logger.warn("Private channel towards management server is not setup. Switch to offline mode and ignore load report");
-		}
-	}
-	
-	public static void ensureRoute(String address) {
-		if(ensureRouteMethod != null) {
-			try {
-				ensureRouteMethod.invoke(ConsoleProxy.context, address);
-			} catch (IllegalAccessException e) {
-				s_logger.error("Unable to invoke ensureRoute due to " + e.getMessage());
-			} catch (InvocationTargetException e) {
-				s_logger.error("Unable to invoke ensureRoute due to " + e.getMessage());
-			}
-		} else {
-			s_logger.warn("Unable to find ensureRoute method, console proxy agent is not up to date");
-		}
-	}
-
-	public static void startWithContext(Properties conf, Object context, byte[] ksBits, String ksPassword) {
-		s_logger.info("Start console proxy with context");
-		if(conf != null) {
-			for(Object key : conf.keySet()) {
-				s_logger.info("Context property " + (String)key + ": " + conf.getProperty((String)key));
-			}
-		}
-		
-		configLog4j();
-		Logger.setFactory(new ConsoleProxyLoggerFactory());
-		
-		// Using reflection to setup private/secure communication channel towards management server
-		ConsoleProxy.context = context;
-		ConsoleProxy.ksBits = ksBits;
-		ConsoleProxy.ksPassword = ksPassword;
-		try {
-			Class<?> contextClazz = Class.forName("com.cloud.agent.resource.consoleproxy.ConsoleProxyResource");
-			authMethod = contextClazz.getDeclaredMethod("authenticateConsoleAccess", String.class, String.class, String.class, String.class, String.class, Boolean.class);
-			reportMethod = contextClazz.getDeclaredMethod("reportLoadInfo", String.class);
-			ensureRouteMethod = contextClazz.getDeclaredMethod("ensureRoute", String.class);
-		} catch (SecurityException e) {
-			s_logger.error("Unable to setup private channel due to SecurityException", e);
-		} catch (NoSuchMethodException e) {
-			s_logger.error("Unable to setup private channel due to NoSuchMethodException", e);
-		} catch (IllegalArgumentException e) {
-			s_logger.error("Unable to setup private channel due to IllegalArgumentException", e);
-		} catch(ClassNotFoundException e) {
-			s_logger.error("Unable to setup private channel due to ClassNotFoundException", e);
-		}
-		
-		// merge properties from conf file
-		InputStream confs = ConsoleProxy.class.getResourceAsStream("/conf/consoleproxy.properties");
-		Properties props = new Properties();
-		if (confs == null) {
-			s_logger.info("Can't load consoleproxy.properties from classpath, will use default configuration");
-		} else {
-			try {
-				props.load(confs);
-				
-				for(Object key : props.keySet()) {
-					// give properties passed via context high priority, treat properties from consoleproxy.properties
-					// as default values
-					if(conf.get(key) == null)
-						conf.put(key, props.get(key));
-				}
-			}  catch (Exception e) {
-				s_logger.error(e.toString(), e);
-			}
-		}
-		
-		start(conf);
-	}
-
-	public static void start(Properties conf) {
-		System.setProperty("java.awt.headless", "true");
-		
-		configProxy(conf);
-		
-		ConsoleProxyServerFactory factory = getHttpServerFactory();
-		if(factory == null) {
-			s_logger.error("Unable to load console proxy server factory");
-			System.exit(1);
-		}
-		
-		if(httpListenPort != 0) {
-			startupHttpMain();
-		} else {
-			s_logger.error("A valid HTTP server port is required to be specified, please check your consoleproxy.httpListenPort settings");
-			System.exit(1);
-		}
-		
-	    if(httpCmdListenPort > 0) {
-	    	startupHttpCmdPort();
-	    } else {
-	    	s_logger.info("HTTP command port is disabled");
-	    }
-	    
-	    ConsoleProxyGCThread cthread = new ConsoleProxyGCThread(connectionMap);
-		cthread.setName("Console Proxy GC Thread");
-		cthread.start();
-	}
-	
-	private static void startupHttpMain() {
-		try {
-			ConsoleProxyServerFactory factory = getHttpServerFactory();
-			if(factory == null) {
-				s_logger.error("Unable to load HTTP server factory");
-				System.exit(1);
-			}
-			
-			HttpServer server = factory.createHttpServerInstance(httpListenPort);
-			server.createContext("/getscreen", new ConsoleProxyThumbnailHandler());
-			server.createContext("/resource/", new ConsoleProxyResourceHandler());
-			server.createContext("/ajax", new ConsoleProxyAjaxHandler());
-			server.createContext("/ajaximg", new ConsoleProxyAjaxImageHandler());
-			server.setExecutor(new ThreadExecutor()); // creates a default executor
-			server.start();
-		} catch(Exception e) {
-			s_logger.error(e.getMessage(), e);
-			System.exit(1);
-		}
-	}
-	
-	private static void startupHttpCmdPort() {
-		try {
-		    s_logger.info("Listening for HTTP CMDs on port " + httpCmdListenPort);
-			HttpServer cmdServer = HttpServer.create(new InetSocketAddress(httpCmdListenPort), 2);
-			cmdServer.createContext("/cmd", new ConsoleProxyCmdHandler());
-			cmdServer.setExecutor(new ThreadExecutor()); // creates a default executor
-			cmdServer.start();
-		} catch(Exception e) {
-			s_logger.error(e.getMessage(), e);
-			System.exit(1);
-		}
-	}
-	
-	public static void main(String[] argv) {
-		standaloneStart = true;
-		configLog4j();
-		Logger.setFactory(new ConsoleProxyLoggerFactory());
-		
-		InputStream confs = ConsoleProxy.class.getResourceAsStream("/conf/consoleproxy.properties");
-		Properties conf = new Properties();
-		if (confs == null) {
-			s_logger.info("Can't load consoleproxy.properties from classpath, will use default configuration");
-		} else {
-			try {
-				conf.load(confs);
-			}  catch (Exception e) {
-				s_logger.error(e.toString(), e);
-			}
-		}
-		start(conf);
-	}
-	
-	public static ConsoleProxyClient getVncViewer(ConsoleProxyClientParam param) throws Exception {
-		ConsoleProxyClient viewer = null;
-		
-		boolean reportLoadChange = false;
-		String clientKey = param.getClientMapKey();
-		synchronized (connectionMap) {
-			viewer = connectionMap.get(clientKey);
-			if (viewer == null) {
-				viewer = new ConsoleProxyVncClient();
-				viewer.initClient(param);
-				connectionMap.put(clientKey, viewer);
-				s_logger.info("Added viewer object " + viewer);
-				
-				reportLoadChange = true;
-			} else if (!viewer.isFrontEndAlive()) {
-				s_logger.info("The rfb thread died, reinitializing the viewer " + viewer);
-				viewer.initClient(param);
-			} else if (!param.getClientHostPassword().equals(viewer.getClientHostPassword())) {
-				s_logger.warn("Bad sid detected(VNC port may be reused). sid in session: " + viewer.getClientHostPassword()
-					+ ", sid in request: " + param.getClientHostPassword());
-				viewer.initClient(param);
-			}
-		}
-		
-		if(reportLoadChange) {
-			ConsoleProxyClientStatsCollector statsCollector = getStatsCollector();
-			String loadInfo = statsCollector.getStatsReport();
-			reportLoadInfo(loadInfo);
-			if(s_logger.isDebugEnabled())
-				s_logger.debug("Report load change : " + loadInfo);
-		}
-		
-		return viewer;
-	}
-	
-	public static ConsoleProxyClient getAjaxVncViewer(ConsoleProxyClientParam param, String ajaxSession) throws Exception {
-		
-		boolean reportLoadChange = false;
-		String clientKey = param.getClientMapKey();
-		synchronized (connectionMap) {
-			ConsoleProxyClient viewer = connectionMap.get(clientKey);
-			if (viewer == null) {
-				viewer = new ConsoleProxyVncClient();
-				viewer.initClient(param);
-				
-				connectionMap.put(clientKey, viewer);
-				s_logger.info("Added viewer object " + viewer);
-				reportLoadChange = true;
-			} else if (!viewer.isFrontEndAlive()) {
-				s_logger.info("The rfb thread died, reinitializing the viewer " + viewer);
-				viewer.initClient(param);
-			} else if (!param.getClientHostPassword().equals(viewer.getClientHostPassword())) {
-				s_logger.warn("Bad sid detected(VNC port may be reused). sid in session: " 
-					+ viewer.getClientHostPassword() + ", sid in request: " + param.getClientHostPassword());
-				viewer.initClient(param);
-			} else {
-				if(ajaxSession == null || ajaxSession.isEmpty())
-					authenticationExternally(param);
-			}
-			
-			if(reportLoadChange) {
-				ConsoleProxyClientStatsCollector statsCollector = getStatsCollector();
-				String loadInfo = statsCollector.getStatsReport();
-				reportLoadInfo(loadInfo);
-				if(s_logger.isDebugEnabled())
-					s_logger.debug("Report load change : " + loadInfo);
-			}
-			return viewer;
-		}
-	}
-	
-	public static void removeViewer(ConsoleProxyClient viewer) {
-		synchronized (connectionMap) {
-			for(Map.Entry<String, ConsoleProxyClient> entry : connectionMap.entrySet()) {
-				if(entry.getValue() == viewer) {
-					connectionMap.remove(entry.getKey());
-					return;
-				}
-			}
-		}
-	}
-	
-	public static ConsoleProxyClientStatsCollector getStatsCollector() {
-		return new ConsoleProxyClientStatsCollector(connectionMap);
-	}
-	
-	public static void authenticationExternally(ConsoleProxyClientParam param) throws AuthenticationException {
-		ConsoleProxyAuthenticationResult authResult = authenticateConsoleAccess(param, false);
-		
-		if(authResult == null || !authResult.isSuccess()) {
-    		s_logger.warn("External authenticator failed authencation request for vm " + param.getClientTag() + " with sid " + param.getClientHostPassword());
-        	
-			throw new AuthenticationException("External authenticator failed request for vm " + param.getClientTag() + " with sid " + param.getClientHostPassword());
-		}
-	}
-	
-	public static ConsoleProxyAuthenticationResult reAuthenticationExternally(ConsoleProxyClientParam param) {
-		return authenticateConsoleAccess(param, true);
-	}
-	
-	public static String getEncryptorPassword() { 
-		return encryptorPassword; 
-	}
-	
-	public static void setEncryptorPassword(String password) {
-		encryptorPassword = password;
-	}
-	
-	static class ThreadExecutor implements Executor {
-	     public void execute(Runnable r) {
-	         new Thread(r).start();
-	     }
-	}
-}
+    public static void start(Properties conf) {
+        System.setProperty("java.awt.headless", "true");
+        
+        configProxy(conf);
+        
+        ConsoleProxyServerFactory factory = getHttpServerFactory();
+        if(factory == null) {
+            s_logger.error("Unable to load console proxy server factory");
+            System.exit(1);
+        }
+        
+        if(httpListenPort != 0) {
+            startupHttpMain();
+        } else {
+            s_logger.error("A valid HTTP server port is required to be specified, please check your consoleproxy.httpListenPort settings");
+            System.exit(1);
+        }
+        
+        if(httpCmdListenPort > 0) {
+            startupHttpCmdPort();
+        } else {
+            s_logger.info("HTTP command port is disabled");
+        }
+        
+        ConsoleProxyGCThread cthread = new ConsoleProxyGCThread(connectionMap);
+        cthread.setName("Console Proxy GC Thread");
+        cthread.start();
+    }
+    
+    private static void startupHttpMain() {
+        try {
+            ConsoleProxyServerFactory factory = getHttpServerFactory();
+            if(factory == null) {
+                s_logger.error("Unable to load HTTP server factory");
+                System.exit(1);
+            }
+            
+            HttpServer server = factory.createHttpServerInstance(httpListenPort);
+            server.createContext("/getscreen", new ConsoleProxyThumbnailHandler());
+            server.createContext("/resource/", new ConsoleProxyResourceHandler());
+            server.createContext("/ajax", new ConsoleProxyAjaxHandler());
+            server.createContext("/ajaximg", new ConsoleProxyAjaxImageHandler());
+            server.setExecutor(new ThreadExecutor()); // creates a default executor
+            server.start();
+        } catch(Exception e) {
+            s_logger.error(e.getMessage(), e);
+            System.exit(1);
+        }
+    }
+    
+    private static void startupHttpCmdPort() {
+        try {
+            s_logger.info("Listening for HTTP CMDs on port " + httpCmdListenPort);
+            HttpServer cmdServer = HttpServer.create(new InetSocketAddress(httpCmdListenPort), 2);
+            cmdServer.createContext("/cmd", new ConsoleProxyCmdHandler());
+            cmdServer.setExecutor(new ThreadExecutor()); // creates a default executor
+            cmdServer.start();
+        } catch(Exception e) {
+            s_logger.error(e.getMessage(), e);
+            System.exit(1);
+        }
+    }
+    
+    public static void main(String[] argv) {
+        standaloneStart = true;
+        configLog4j();
+        Logger.setFactory(new ConsoleProxyLoggerFactory());
+        
+        InputStream confs = ConsoleProxy.class.getResourceAsStream("/conf/consoleproxy.properties");
+        Properties conf = new Properties();
+        if (confs == null) {
+            s_logger.info("Can't load consoleproxy.properties from classpath, will use default configuration");
+        } else {
+            try {
+                conf.load(confs);
+            }  catch (Exception e) {
+                s_logger.error(e.toString(), e);
+            }
+        }
+        start(conf);
+    }
+    
+    public static ConsoleProxyClient getVncViewer(ConsoleProxyClientParam param) throws Exception {
+        ConsoleProxyClient viewer = null;
+        
+        boolean reportLoadChange = false;
+        String clientKey = param.getClientMapKey();
+        synchronized (connectionMap) {
+            viewer = connectionMap.get(clientKey);
+            if (viewer == null) {
+                viewer = new ConsoleProxyVncClient();
+                viewer.initClient(param);
+                connectionMap.put(clientKey, viewer);
+                s_logger.info("Added viewer object " + viewer);
+                
+                reportLoadChange = true;
+            } else if (!viewer.isFrontEndAlive()) {
+                s_logger.info("The rfb thread died, reinitializing the viewer " + viewer);
+                viewer.initClient(param);
+            } else if (!param.getClientHostPassword().equals(viewer.getClientHostPassword())) {
+                s_logger.warn("Bad sid detected(VNC port may be reused). sid in session: " + viewer.getClientHostPassword()
+                    + ", sid in request: " + param.getClientHostPassword());
+                viewer.initClient(param);
+            }
+        }
+        
+        if(reportLoadChange) {
+            ConsoleProxyClientStatsCollector statsCollector = getStatsCollector();
+            String loadInfo = statsCollector.getStatsReport();
+            reportLoadInfo(loadInfo);
+            if(s_logger.isDebugEnabled())
+                s_logger.debug("Report load change : " + loadInfo);
+        }
+        
+        return viewer;
+    }
+    
+    public static ConsoleProxyClient getAjaxVncViewer(ConsoleProxyClientParam param, String ajaxSession) throws Exception {
+        
+        boolean reportLoadChange = false;
+        String clientKey = param.getClientMapKey();
+        synchronized (connectionMap) {
+            ConsoleProxyClient viewer = connectionMap.get(clientKey);
+            if (viewer == null) {
+                viewer = new ConsoleProxyVncClient();
+                viewer.initClient(param);
+                
+                connectionMap.put(clientKey, viewer);
+                s_logger.info("Added viewer object " + viewer);
+                reportLoadChange = true;
+            } else if (!viewer.isFrontEndAlive()) {
+                s_logger.info("The rfb thread died, reinitializing the viewer " + viewer);
+                viewer.initClient(param);
+            } else if (!param.getClientHostPassword().equals(viewer.getClientHostPassword())) {
+                s_logger.warn("Bad sid detected(VNC port may be reused). sid in session: " 
+                    + viewer.getClientHostPassword() + ", sid in request: " + param.getClientHostPassword());
+                viewer.initClient(param);
+            } else {
+                if(ajaxSession == null || ajaxSession.isEmpty())
+                    authenticationExternally(param);
+            }
+            
+            if(reportLoadChange) {
+                ConsoleProxyClientStatsCollector statsCollector = getStatsCollector();
+                String loadInfo = statsCollector.getStatsReport();
+                reportLoadInfo(loadInfo);
+                if(s_logger.isDebugEnabled())
+                    s_logger.debug("Report load change : " + loadInfo);
+            }
+            return viewer;
+        }
+    }
+    
+    public static void removeViewer(ConsoleProxyClient viewer) {
+        synchronized (connectionMap) {
+            for(Map.Entry<String, ConsoleProxyClient> entry : connectionMap.entrySet()) {
+                if(entry.getValue() == viewer) {
+                    connectionMap.remove(entry.getKey());
+                    return;
+                }
+            }
+        }
+    }
+    
+    public static ConsoleProxyClientStatsCollector getStatsCollector() {
+        return new ConsoleProxyClientStatsCollector(connectionMap);
+    }
+    
+    public static void authenticationExternally(ConsoleProxyClientParam param) throws AuthenticationException {
+        ConsoleProxyAuthenticationResult authResult = authenticateConsoleAccess(param, false);
+        
+        if(authResult == null || !authResult.isSuccess()) {
+            s_logger.warn("External authenticator failed authencation request for vm " + param.getClientTag() + " with sid " + param.getClientHostPassword());
+            
+            throw new AuthenticationException("External authenticator failed request for vm " + param.getClientTag() + " with sid " + param.getClientHostPassword());
+        }
+    }
+    
+    public static ConsoleProxyAuthenticationResult reAuthenticationExternally(ConsoleProxyClientParam param) {
+        return authenticateConsoleAccess(param, true);
+    }
+    
+    public static String getEncryptorPassword() { 
+        return encryptorPassword; 
+    }
+    
+    public static void setEncryptorPassword(String password) {
+        encryptorPassword = password;
+    }
+    
+    static class ThreadExecutor implements Executor {
+         public void execute(Runnable r) {
+             new Thread(r).start();
+         }
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/b25122bd/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClient.java
----------------------------------------------------------------------
diff --git a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClient.java b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClient.java
index 594b2ae..8a0be05 100644
--- a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClient.java
+++ b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClient.java
@@ -14,57 +14,56 @@
 // 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.Image;
-import java.util.List;
-
-/**
- * @author Kelven Yang
- * ConsoleProxyClient defines an standard interface that a console client should implement,
- * 
- * ConsoleProxyClient maintains a session towards the target host, it glues the session
- * to a AJAX front-end viewer 
- */
-public interface ConsoleProxyClient {
-	int getClientId();
-	
-	//
-	// Quick status
-	//
-	boolean isHostConnected();
-	boolean isFrontEndAlive();
-
-	//
-	// AJAX viewer
-	//
-	long getAjaxSessionId();
-	AjaxFIFOImageCache getAjaxImageCache();
-	Image getClientScaledImage(int width, int height);					// client thumbnail support
-	
-	String onAjaxClientStart(String title, List<String> languages, String guest);
-	String onAjaxClientUpdate();
-	String onAjaxClientKickoff();
-
-	//
-	// Input handling
-	//
-	void sendClientRawKeyboardEvent(InputEventType event, int code, int modifiers);
-	void sendClientMouseEvent(InputEventType event, int x, int y, int code, int modifiers);
-
-	//
-	// Info/Stats
-	//
-	long getClientCreateTime();
-	long getClientLastFrontEndActivityTime();
-	String getClientHostAddress();
-	int getClientHostPort();
-	String getClientHostPassword();
-	String getClientTag();
-
-	//
-	// Setup/house-keeping
-	//
-	void initClient(ConsoleProxyClientParam param);
-	void closeClient();
-}
+package com.cloud.consoleproxy;
+
+import java.awt.Image;
+import java.util.List;
+
+/**
+ * ConsoleProxyClient defines an standard interface that a console client should implement,
+ * 
+ * ConsoleProxyClient maintains a session towards the target host, it glues the session
+ * to a AJAX front-end viewer 
+ */
+public interface ConsoleProxyClient {
+    int getClientId();
+    
+    //
+    // Quick status
+    //
+    boolean isHostConnected();
+    boolean isFrontEndAlive();
+
+    //
+    // AJAX viewer
+    //
+    long getAjaxSessionId();
+    AjaxFIFOImageCache getAjaxImageCache();
+    Image getClientScaledImage(int width, int height);                  // client thumbnail support
+    
+    String onAjaxClientStart(String title, List<String> languages, String guest);
+    String onAjaxClientUpdate();
+    String onAjaxClientKickoff();
+
+    //
+    // Input handling
+    //
+    void sendClientRawKeyboardEvent(InputEventType event, int code, int modifiers);
+    void sendClientMouseEvent(InputEventType event, int x, int y, int code, int modifiers);
+
+    //
+    // Info/Stats
+    //
+    long getClientCreateTime();
+    long getClientLastFrontEndActivityTime();
+    String getClientHostAddress();
+    int getClientHostPort();
+    String getClientHostPassword();
+    String getClientTag();
+
+    //
+    // Setup/house-keeping
+    //
+    void initClient(ConsoleProxyClientParam param);
+    void closeClient();
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/b25122bd/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClientBase.java
----------------------------------------------------------------------
diff --git a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClientBase.java b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClientBase.java
index ac38f5f..e4f4727 100644
--- a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClientBase.java
+++ b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClientBase.java
@@ -14,445 +14,443 @@
 // 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.Image;
-import java.awt.Rectangle;
-import java.util.List;
-
-import org.apache.log4j.Logger;
-
-import com.cloud.consoleproxy.util.TileInfo;
-import com.cloud.consoleproxy.util.TileTracker;
-import com.cloud.consoleproxy.vnc.FrameBufferCanvas;
-
-/**
- * 
- * @author Kelven Yang
- * 
- * an instance of specialized console protocol implementation, such as VNC or RDP
- * 
- * It mainly implements the features needed by front-end AJAX viewer
- * 
- */
-public abstract class ConsoleProxyClientBase implements ConsoleProxyClient, ConsoleProxyClientListener {
-	private static final Logger s_logger = Logger.getLogger(ConsoleProxyClientBase.class);
-	
-	private static int s_nextClientId = 0;
-	protected int clientId = getNextClientId();
-	
-	protected long ajaxSessionId = 0;
-	
-	protected boolean dirtyFlag = false;
-	protected Object tileDirtyEvent = new Object();
-	protected TileTracker tracker;
-	protected AjaxFIFOImageCache ajaxImageCache = new AjaxFIFOImageCache(2);
+package com.cloud.consoleproxy;
 
-	protected ConsoleProxyClientParam clientParam;
-	protected String clientToken;
-	
-	protected long createTime = System.currentTimeMillis();
-	protected long lastFrontEndActivityTime = System.currentTimeMillis();
-
-	protected boolean framebufferResized = false;
-	protected int resizedFramebufferWidth;
-	protected int resizedFramebufferHeight;
-
-	public ConsoleProxyClientBase() {
-		tracker = new TileTracker();
-		tracker.initTracking(64, 64, 800, 600);
-	}
-
-	//
-	// interface ConsoleProxyClient
-	//
-	@Override
-	public int getClientId() {
-		return clientId;
-	}
-	
-	public abstract boolean isHostConnected();
-	public abstract boolean isFrontEndAlive();
-
-	@Override
-	public long getAjaxSessionId() {
-		return this.ajaxSessionId;
-	}
-	
-	@Override
-	public AjaxFIFOImageCache getAjaxImageCache() {
-		return ajaxImageCache;
-	}
-	
-	public Image getClientScaledImage(int width, int height) {
-		FrameBufferCanvas canvas = getFrameBufferCavas();
-		if(canvas != null)
-			return canvas.getFrameBufferScaledImage(width, height);
-		
-		return null;
-	}
-	
-	public abstract void sendClientRawKeyboardEvent(InputEventType event, int code, int modifiers);
-	public abstract void sendClientMouseEvent(InputEventType event, int x, int y, int code, int modifiers);
-	
-	@Override
-	public long getClientCreateTime() {
-		return createTime;
-	}
-	
-	@Override
-	public long getClientLastFrontEndActivityTime() {
-		return lastFrontEndActivityTime;
-	}
-	
-	@Override
-	public String getClientHostAddress() {
-		return clientParam.getClientHostAddress();
-	}
-	
-	@Override
-	public int getClientHostPort() {
-		return clientParam.getClientHostPort();
-	}
-	
-	@Override
-	public String getClientHostPassword() {
-		return clientParam.getClientHostPassword();
-	}
-	
-	@Override
-	public String getClientTag() {
-		if(clientParam.getClientTag() != null)
-			return clientParam.getClientTag();
-		return "";
-	}
-
-	@Override
-	public abstract void initClient(ConsoleProxyClientParam param);
-		
-	@Override
-	public abstract void closeClient();
-	
-	//
-	// interface FrameBufferEventListener
-	//
-	@Override
-	public void onFramebufferSizeChange(int w, int h) {
-		tracker.resize(w, h);
-
-		synchronized(this) {
-			framebufferResized = true;
-			resizedFramebufferWidth = w;
-			resizedFramebufferHeight = h;
-		}
-		
-		signalTileDirtyEvent();
-	}
-
-	@Override
-	public void onFramebufferUpdate(int x, int y, int w, int h) {
-		if(s_logger.isTraceEnabled())
-			s_logger.trace("Frame buffer update {" + x + "," + y + "," + w + "," + h + "}");
-		tracker.invalidate(new Rectangle(x, y, w, h));
-		
-		signalTileDirtyEvent();
-	}
-	
-	//
-	// AJAX Image manipulation 
-	//
-	public byte[] getFrameBufferJpeg() {
-		FrameBufferCanvas canvas = getFrameBufferCavas();
-		if(canvas != null)
-			return canvas.getFrameBufferJpeg();
-		
-		return null;
-	}
-	
-	public byte[] getTilesMergedJpeg(List<TileInfo> tileList, int tileWidth, int tileHeight) {
-		FrameBufferCanvas canvas = getFrameBufferCavas();
-		if(canvas != null)
-			return canvas.getTilesMergedJpeg(tileList, tileWidth, tileHeight);
-		return null;
-	}
-	
-	private String prepareAjaxImage(List<TileInfo> tiles, boolean init) {
-		byte[] imgBits;
-		if(init)
-			imgBits = getFrameBufferJpeg();
-		else 
-			imgBits = getTilesMergedJpeg(tiles, tracker.getTileWidth(), tracker.getTileHeight());
-		
-		if(imgBits == null) {
-			s_logger.warn("Unable to generate jpeg image");
-		} else {
-			if(s_logger.isTraceEnabled())
-				s_logger.trace("Generated jpeg image size: " + imgBits.length);
-		}
-		
-		int key = ajaxImageCache.putImage(imgBits);
-		StringBuffer sb = new StringBuffer();
-		sb.append("/ajaximg?token=").append(clientToken);
-		sb.append("&key=").append(key);
-		sb.append("&ts=").append(System.currentTimeMillis());
-		
-		return sb.toString();
-	}
-	
-	private String prepareAjaxSession(boolean init) {
-		if(init) {
-			synchronized(this) {
-				ajaxSessionId++;
-			}
-		}
-
-		StringBuffer sb = new StringBuffer();
-		sb.append("/ajax?token=").append(clientToken).append("&sess=").append(ajaxSessionId);
-		return sb.toString();
-	}
-
-	@Override
-	public String onAjaxClientKickoff() {
-		return "onKickoff();";
-	}
-	
-	private boolean waitForViewerReady() {
-		long startTick = System.currentTimeMillis();
-		while(System.currentTimeMillis() - startTick < 5000) {
-			if(getFrameBufferCavas() != null)
-				return true;
-			
-			try {
-				Thread.sleep(100);
-			} catch (InterruptedException e) {
-			}
-		}
-		return false;
-	}
-	
-	private String onAjaxClientConnectFailed() {
-		return "<html><head></head><body><div id=\"main_panel\" tabindex=\"1\"><p>" + 
-			"Unable to start console session as connection is refused by the machine you are accessing" +
-			"</p></div></body></html>";
-	}
-
-	@Override
-	public String onAjaxClientStart(String title, List<String> languages, String guest) {
-		updateFrontEndActivityTime();
-		
-		if(!waitForViewerReady())
-			return onAjaxClientConnectFailed();
-		
-		synchronized(this) {
-			ajaxSessionId++;
-			framebufferResized = false;
-		}
-		
-		int tileWidth = tracker.getTileWidth();
-		int tileHeight = tracker.getTileHeight();
-		int width = tracker.getTrackWidth();
-		int height = tracker.getTrackHeight();
-		
-		if(s_logger.isTraceEnabled())
-			s_logger.trace("Ajax client start, frame buffer w: " + width + ", " + height);
-		
-		int retry = 0;
-		tracker.initCoverageTest();
-		while(!tracker.hasFullCoverage() && retry < 10) {
-			try {
-				Thread.sleep(1000);
-			} catch (InterruptedException e) {
-			}
-			retry++;
-		}
-		
-		List<TileInfo> tiles = tracker.scan(true);
-		String imgUrl = prepareAjaxImage(tiles, true);
-		String updateUrl = prepareAjaxSession(true);
-		
-		StringBuffer sbTileSequence = new StringBuffer();
-		int i = 0;
-		for(TileInfo tile : tiles) {
-			sbTileSequence.append("[").append(tile.getRow()).append(",").append(tile.getCol()).append("]");
-			if(i < tiles.size() - 1)
-				sbTileSequence.append(",");
-			
-			i++;
-		}
-
-		return getAjaxViewerPageContent(sbTileSequence.toString(), imgUrl, 
-			updateUrl, width, height, tileWidth, tileHeight, title, 
-			ConsoleProxy.keyboardType == ConsoleProxy.KEYBOARD_RAW, 
-			languages, guest);
-	}
-	
-	private String getAjaxViewerPageContent(String tileSequence, String imgUrl, String updateUrl, int width,
-		int height, int tileWidth, int tileHeight, String title, boolean rawKeyboard, List<String> languages, String guest) {
-
-		StringBuffer sbLanguages = new StringBuffer("");
-		if(languages != null) {
-			for(String lang : languages) {
-				if(sbLanguages.length() > 0) {
-					sbLanguages.append(",");
-				}
-				sbLanguages.append(lang);
-			}
-		}
-		
-		String[] content = new String[] {
-			"<html>",
-			"<head>",
-			"<script type=\"text/javascript\" language=\"javascript\" src=\"/resource/js/jquery.js\"></script>",
-			"<script type=\"text/javascript\" language=\"javascript\" src=\"/resource/js/cloud.logger.js\"></script>",
-			"<script type=\"text/javascript\" language=\"javascript\" src=\"/resource/js/ajaxviewer.js\"></script>",
-			"<script type=\"text/javascript\" language=\"javascript\" src=\"/resource/js/handler.js\"></script>",
-			"<link rel=\"stylesheet\" type=\"text/css\" href=\"/resource/css/ajaxviewer.css\"></link>",
-			"<link rel=\"stylesheet\" type=\"text/css\" href=\"/resource/css/logger.css\"></link>",
-			"<title>" + title + "</title>",
-			"</head>",
-			"<body>",
-			"<div id=\"toolbar\">",
-			"<ul>",
-				"<li>", 
-					"<a href=\"#\" cmd=\"sendCtrlAltDel\">", 
-						"<span><img align=\"left\" src=\"/resource/images/cad.gif\" alt=\"Ctrl-Alt-Del\" />Ctrl-Alt-Del</span>", 
-					"</a>", 
-				"</li>",
-				"<li>", 
-					"<a href=\"#\" cmd=\"sendCtrlEsc\">", 
-						"<span><img align=\"left\" src=\"/resource/images/winlog.png\" alt=\"Ctrl-Esc\" style=\"width:16px;height:16px\"/>Ctrl-Esc</span>",
-					"</a>", 
-				"</li>",
-				
-				"<li class=\"pulldown\">", 
-					"<a href=\"#\">", 
-						"<span><img align=\"left\" src=\"/resource/images/winlog.png\" alt=\"Keyboard\" style=\"width:16px;height:16px\"/>Keyboard</span>",
-					"</a>", 
-					"<ul>",
-		    			"<li><a href=\"#\" cmd=\"keyboard_us\"><span>Standard (US) keyboard</span></a></li>",
-		    			"<li><a href=\"#\" cmd=\"keyboard_jp\"><span>Japanese keyboard</span></a></li>",
-					"</ul>",
-				"</li>",
-			"</ul>",
-			"<span id=\"light\" class=\"dark\" cmd=\"toggle_logwin\"></span>", 
-			"</div>",
-			"<div id=\"main_panel\" tabindex=\"1\"></div>",
-			"<script language=\"javascript\">",
-			"var acceptLanguages = '" + sbLanguages.toString() + "';",
-			"var tileMap = [ " + tileSequence + " ];",
-			"var ajaxViewer = new AjaxViewer('main_panel', '" + imgUrl + "', '" + updateUrl + "', tileMap, ", 
-				String.valueOf(width) + ", " + String.valueOf(height) + ", " + String.valueOf(tileWidth) + ", " + String.valueOf(tileHeight) + ");",
-
-			"$(function() {",
-				"ajaxViewer.start();",
-			"});",
-
-			"</script>",
-			"</body>",
-			"</html>"	
-		};
-		
-		StringBuffer sb = new StringBuffer();
-		for(int i = 0; i < content.length; i++)
-			sb.append(content[i]);
-		
-		return sb.toString();
-	}
-	
-	public String onAjaxClientDisconnected() {
-		return "onDisconnect();";
-	}
-
-	@Override
-	public String onAjaxClientUpdate() {
-		updateFrontEndActivityTime();
-		if(!waitForViewerReady())
-			return onAjaxClientDisconnected();
-		
-		synchronized(tileDirtyEvent) {
-			if(!dirtyFlag) {
-				try {
-					tileDirtyEvent.wait(3000);
-				} catch(InterruptedException e) {
-				}
-			}
-		}
-		
-		boolean doResize = false;
-		synchronized(this) {
-			if(framebufferResized) {
-				framebufferResized = false;
-				doResize = true;
-			}
-		}
-		
-		List<TileInfo> tiles;
-		
-		if(doResize)
-			tiles = tracker.scan(true);
-		else
-			tiles = tracker.scan(false);
-		dirtyFlag = false;
-		
-		String imgUrl = prepareAjaxImage(tiles, false);
-		StringBuffer sbTileSequence = new StringBuffer();
-		int i = 0;
-		for(TileInfo tile : tiles) {
-			sbTileSequence.append("[").append(tile.getRow()).append(",").append(tile.getCol()).append("]");
-			if(i < tiles.size() - 1)
-				sbTileSequence.append(",");
-			
-			i++;
-		}
-
-		return getAjaxViewerUpdatePageContent(sbTileSequence.toString(), imgUrl, doResize, 
-			resizedFramebufferWidth, resizedFramebufferHeight, 
-			tracker.getTileWidth(), tracker.getTileHeight());
-	}
-	
-	private String getAjaxViewerUpdatePageContent(String tileSequence, String imgUrl, boolean resized, int width,
-		int height, int tileWidth, int tileHeight) {
-		
-		String[] content = new String[] {
-			"tileMap = [ " + tileSequence + " ];",
-			resized ? "ajaxViewer.resize('main_panel', " + width + ", " + height + " , " + tileWidth + ", " + tileHeight + ");" : "", 
-			"ajaxViewer.refresh('" + imgUrl + "', tileMap, false);"
-		};
-		
-		StringBuffer sb = new StringBuffer();
-		for(int i = 0; i < content.length; i++)
-			sb.append(content[i]);
-		
-		return sb.toString();
-	}
-	
-	//
-	// Helpers
-	//
-	private synchronized static int getNextClientId() {
-		return ++s_nextClientId;
-	}
-	
-	private void signalTileDirtyEvent() {
-		synchronized(tileDirtyEvent) {
-			dirtyFlag = true;
-			tileDirtyEvent.notifyAll();
-		}
-	}
-	
-	public void updateFrontEndActivityTime() {
-		lastFrontEndActivityTime = System.currentTimeMillis(); 
-	}
-
-	protected abstract FrameBufferCanvas getFrameBufferCavas();
+import java.awt.Image;
+import java.awt.Rectangle;
+import java.util.List;
 
-	public ConsoleProxyClientParam getClientParam() {
-		return clientParam;
-	}
+import org.apache.log4j.Logger;
 
-	public void setClientParam(ConsoleProxyClientParam clientParam) {
-		this.clientParam = clientParam;
-		ConsoleProxyPasswordBasedEncryptor encryptor = new ConsoleProxyPasswordBasedEncryptor(ConsoleProxy.getEncryptorPassword());
-		this.clientToken = encryptor.encryptObject(ConsoleProxyClientParam.class, clientParam);
-	}
-}
+import com.cloud.consoleproxy.util.TileInfo;
+import com.cloud.consoleproxy.util.TileTracker;
+import com.cloud.consoleproxy.vnc.FrameBufferCanvas;
+
+/**
+ * 
+ * an instance of specialized console protocol implementation, such as VNC or RDP
+ * 
+ * It mainly implements the features needed by front-end AJAX viewer
+ * 
+ */
+public abstract class ConsoleProxyClientBase implements ConsoleProxyClient, ConsoleProxyClientListener {
+    private static final Logger s_logger = Logger.getLogger(ConsoleProxyClientBase.class);
+    
+    private static int s_nextClientId = 0;
+    protected int clientId = getNextClientId();
+    
+    protected long ajaxSessionId = 0;
+    
+    protected boolean dirtyFlag = false;
+    protected Object tileDirtyEvent = new Object();
+    protected TileTracker tracker;
+    protected AjaxFIFOImageCache ajaxImageCache = new AjaxFIFOImageCache(2);
+
+    protected ConsoleProxyClientParam clientParam;
+    protected String clientToken;
+    
+    protected long createTime = System.currentTimeMillis();
+    protected long lastFrontEndActivityTime = System.currentTimeMillis();
+
+    protected boolean framebufferResized = false;
+    protected int resizedFramebufferWidth;
+    protected int resizedFramebufferHeight;
+
+    public ConsoleProxyClientBase() {
+        tracker = new TileTracker();
+        tracker.initTracking(64, 64, 800, 600);
+    }
+
+    //
+    // interface ConsoleProxyClient
+    //
+    @Override
+    public int getClientId() {
+        return clientId;
+    }
+    
+    public abstract boolean isHostConnected();
+    public abstract boolean isFrontEndAlive();
+
+    @Override
+    public long getAjaxSessionId() {
+        return this.ajaxSessionId;
+    }
+    
+    @Override
+    public AjaxFIFOImageCache getAjaxImageCache() {
+        return ajaxImageCache;
+    }
+    
+    public Image getClientScaledImage(int width, int height) {
+        FrameBufferCanvas canvas = getFrameBufferCavas();
+        if(canvas != null)
+            return canvas.getFrameBufferScaledImage(width, height);
+        
+        return null;
+    }
+    
+    public abstract void sendClientRawKeyboardEvent(InputEventType event, int code, int modifiers);
+    public abstract void sendClientMouseEvent(InputEventType event, int x, int y, int code, int modifiers);
+    
+    @Override
+    public long getClientCreateTime() {
+        return createTime;
+    }
+    
+    @Override
+    public long getClientLastFrontEndActivityTime() {
+        return lastFrontEndActivityTime;
+    }
+    
+    @Override
+    public String getClientHostAddress() {
+        return clientParam.getClientHostAddress();
+    }
+    
+    @Override
+    public int getClientHostPort() {
+        return clientParam.getClientHostPort();
+    }
+    
+    @Override
+    public String getClientHostPassword() {
+        return clientParam.getClientHostPassword();
+    }
+    
+    @Override
+    public String getClientTag() {
+        if(clientParam.getClientTag() != null)
+            return clientParam.getClientTag();
+        return "";
+    }
+
+    @Override
+    public abstract void initClient(ConsoleProxyClientParam param);
+        
+    @Override
+    public abstract void closeClient();
+    
+    //
+    // interface FrameBufferEventListener
+    //
+    @Override
+    public void onFramebufferSizeChange(int w, int h) {
+        tracker.resize(w, h);
+
+        synchronized(this) {
+            framebufferResized = true;
+            resizedFramebufferWidth = w;
+            resizedFramebufferHeight = h;
+        }
+        
+        signalTileDirtyEvent();
+    }
+
+    @Override
+    public void onFramebufferUpdate(int x, int y, int w, int h) {
+        if(s_logger.isTraceEnabled())
+            s_logger.trace("Frame buffer update {" + x + "," + y + "," + w + "," + h + "}");
+        tracker.invalidate(new Rectangle(x, y, w, h));
+        
+        signalTileDirtyEvent();
+    }
+    
+    //
+    // AJAX Image manipulation 
+    //
+    public byte[] getFrameBufferJpeg() {
+        FrameBufferCanvas canvas = getFrameBufferCavas();
+        if(canvas != null)
+            return canvas.getFrameBufferJpeg();
+        
+        return null;
+    }
+    
+    public byte[] getTilesMergedJpeg(List<TileInfo> tileList, int tileWidth, int tileHeight) {
+        FrameBufferCanvas canvas = getFrameBufferCavas();
+        if(canvas != null)
+            return canvas.getTilesMergedJpeg(tileList, tileWidth, tileHeight);
+        return null;
+    }
+    
+    private String prepareAjaxImage(List<TileInfo> tiles, boolean init) {
+        byte[] imgBits;
+        if(init)
+            imgBits = getFrameBufferJpeg();
+        else 
+            imgBits = getTilesMergedJpeg(tiles, tracker.getTileWidth(), tracker.getTileHeight());
+        
+        if(imgBits == null) {
+            s_logger.warn("Unable to generate jpeg image");
+        } else {
+            if(s_logger.isTraceEnabled())
+                s_logger.trace("Generated jpeg image size: " + imgBits.length);
+        }
+        
+        int key = ajaxImageCache.putImage(imgBits);
+        StringBuffer sb = new StringBuffer();
+        sb.append("/ajaximg?token=").append(clientToken);
+        sb.append("&key=").append(key);
+        sb.append("&ts=").append(System.currentTimeMillis());
+        
+        return sb.toString();
+    }
+    
+    private String prepareAjaxSession(boolean init) {
+        if(init) {
+            synchronized(this) {
+                ajaxSessionId++;
+            }
+        }
+
+        StringBuffer sb = new StringBuffer();
+        sb.append("/ajax?token=").append(clientToken).append("&sess=").append(ajaxSessionId);
+        return sb.toString();
+    }
+
+    @Override
+    public String onAjaxClientKickoff() {
+        return "onKickoff();";
+    }
+    
+    private boolean waitForViewerReady() {
+        long startTick = System.currentTimeMillis();
+        while(System.currentTimeMillis() - startTick < 5000) {
+            if(getFrameBufferCavas() != null)
+                return true;
+            
+            try {
+                Thread.sleep(100);
+            } catch (InterruptedException e) {
+            }
+        }
+        return false;
+    }
+    
+    private String onAjaxClientConnectFailed() {
+        return "<html><head></head><body><div id=\"main_panel\" tabindex=\"1\"><p>" + 
+            "Unable to start console session as connection is refused by the machine you are accessing" +
+            "</p></div></body></html>";
+    }
+
+    @Override
+    public String onAjaxClientStart(String title, List<String> languages, String guest) {
+        updateFrontEndActivityTime();
+        
+        if(!waitForViewerReady())
+            return onAjaxClientConnectFailed();
+        
+        synchronized(this) {
+            ajaxSessionId++;
+            framebufferResized = false;
+        }
+        
+        int tileWidth = tracker.getTileWidth();
+        int tileHeight = tracker.getTileHeight();
+        int width = tracker.getTrackWidth();
+        int height = tracker.getTrackHeight();
+        
+        if(s_logger.isTraceEnabled())
+            s_logger.trace("Ajax client start, frame buffer w: " + width + ", " + height);
+        
+        int retry = 0;
+        tracker.initCoverageTest();
+        while(!tracker.hasFullCoverage() && retry < 10) {
+            try {
+                Thread.sleep(1000);
+            } catch (InterruptedException e) {
+            }
+            retry++;
+        }
+        
+        List<TileInfo> tiles = tracker.scan(true);
+        String imgUrl = prepareAjaxImage(tiles, true);
+        String updateUrl = prepareAjaxSession(true);
+        
+        StringBuffer sbTileSequence = new StringBuffer();
+        int i = 0;
+        for(TileInfo tile : tiles) {
+            sbTileSequence.append("[").append(tile.getRow()).append(",").append(tile.getCol()).append("]");
+            if(i < tiles.size() - 1)
+                sbTileSequence.append(",");
+            
+            i++;
+        }
+
+        return getAjaxViewerPageContent(sbTileSequence.toString(), imgUrl, 
+            updateUrl, width, height, tileWidth, tileHeight, title, 
+            ConsoleProxy.keyboardType == ConsoleProxy.KEYBOARD_RAW, 
+            languages, guest);
+    }
+    
+    private String getAjaxViewerPageContent(String tileSequence, String imgUrl, String updateUrl, int width,
+        int height, int tileWidth, int tileHeight, String title, boolean rawKeyboard, List<String> languages, String guest) {
+
+        StringBuffer sbLanguages = new StringBuffer("");
+        if(languages != null) {
+            for(String lang : languages) {
+                if(sbLanguages.length() > 0) {
+                    sbLanguages.append(",");
+                }
+                sbLanguages.append(lang);
+            }
+        }
+        
+        String[] content = new String[] {
+            "<html>",
+            "<head>",
+            "<script type=\"text/javascript\" language=\"javascript\" src=\"/resource/js/jquery.js\"></script>",
+            "<script type=\"text/javascript\" language=\"javascript\" src=\"/resource/js/cloud.logger.js\"></script>",
+            "<script type=\"text/javascript\" language=\"javascript\" src=\"/resource/js/ajaxviewer.js\"></script>",
+            "<script type=\"text/javascript\" language=\"javascript\" src=\"/resource/js/handler.js\"></script>",
+            "<link rel=\"stylesheet\" type=\"text/css\" href=\"/resource/css/ajaxviewer.css\"></link>",
+            "<link rel=\"stylesheet\" type=\"text/css\" href=\"/resource/css/logger.css\"></link>",
+            "<title>" + title + "</title>",
+            "</head>",
+            "<body>",
+            "<div id=\"toolbar\">",
+            "<ul>",
+                "<li>", 
+                    "<a href=\"#\" cmd=\"sendCtrlAltDel\">", 
+                        "<span><img align=\"left\" src=\"/resource/images/cad.gif\" alt=\"Ctrl-Alt-Del\" />Ctrl-Alt-Del</span>", 
+                    "</a>", 
+                "</li>",
+                "<li>", 
+                    "<a href=\"#\" cmd=\"sendCtrlEsc\">", 
+                        "<span><img align=\"left\" src=\"/resource/images/winlog.png\" alt=\"Ctrl-Esc\" style=\"width:16px;height:16px\"/>Ctrl-Esc</span>",
+                    "</a>", 
+                "</li>",
+                
+                "<li class=\"pulldown\">", 
+                    "<a href=\"#\">", 
+                        "<span><img align=\"left\" src=\"/resource/images/winlog.png\" alt=\"Keyboard\" style=\"width:16px;height:16px\"/>Keyboard</span>",
+                    "</a>", 
+                    "<ul>",
+                        "<li><a href=\"#\" cmd=\"keyboard_us\"><span>Standard (US) keyboard</span></a></li>",
+                        "<li><a href=\"#\" cmd=\"keyboard_jp\"><span>Japanese keyboard</span></a></li>",
+                    "</ul>",
+                "</li>",
+            "</ul>",
+            "<span id=\"light\" class=\"dark\" cmd=\"toggle_logwin\"></span>", 
+            "</div>",
+            "<div id=\"main_panel\" tabindex=\"1\"></div>",
+            "<script language=\"javascript\">",
+            "var acceptLanguages = '" + sbLanguages.toString() + "';",
+            "var tileMap = [ " + tileSequence + " ];",
+            "var ajaxViewer = new AjaxViewer('main_panel', '" + imgUrl + "', '" + updateUrl + "', tileMap, ", 
+                String.valueOf(width) + ", " + String.valueOf(height) + ", " + String.valueOf(tileWidth) + ", " + String.valueOf(tileHeight) + ");",
+
+            "$(function() {",
+                "ajaxViewer.start();",
+            "});",
+
+            "</script>",
+            "</body>",
+            "</html>"   
+        };
+        
+        StringBuffer sb = new StringBuffer();
+        for(int i = 0; i < content.length; i++)
+            sb.append(content[i]);
+        
+        return sb.toString();
+    }
+    
+    public String onAjaxClientDisconnected() {
+        return "onDisconnect();";
+    }
+
+    @Override
+    public String onAjaxClientUpdate() {
+        updateFrontEndActivityTime();
+        if(!waitForViewerReady())
+            return onAjaxClientDisconnected();
+        
+        synchronized(tileDirtyEvent) {
+            if(!dirtyFlag) {
+                try {
+                    tileDirtyEvent.wait(3000);
+                } catch(InterruptedException e) {
+                }
+            }
+        }
+        
+        boolean doResize = false;
+        synchronized(this) {
+            if(framebufferResized) {
+                framebufferResized = false;
+                doResize = true;
+            }
+        }
+        
+        List<TileInfo> tiles;
+        
+        if(doResize)
+            tiles = tracker.scan(true);
+        else
+            tiles = tracker.scan(false);
+        dirtyFlag = false;
+        
+        String imgUrl = prepareAjaxImage(tiles, false);
+        StringBuffer sbTileSequence = new StringBuffer();
+        int i = 0;
+        for(TileInfo tile : tiles) {
+            sbTileSequence.append("[").append(tile.getRow()).append(",").append(tile.getCol()).append("]");
+            if(i < tiles.size() - 1)
+                sbTileSequence.append(",");
+            
+            i++;
+        }
+
+        return getAjaxViewerUpdatePageContent(sbTileSequence.toString(), imgUrl, doResize, 
+            resizedFramebufferWidth, resizedFramebufferHeight, 
+            tracker.getTileWidth(), tracker.getTileHeight());
+    }
+    
+    private String getAjaxViewerUpdatePageContent(String tileSequence, String imgUrl, boolean resized, int width,
+        int height, int tileWidth, int tileHeight) {
+        
+        String[] content = new String[] {
+            "tileMap = [ " + tileSequence + " ];",
+            resized ? "ajaxViewer.resize('main_panel', " + width + ", " + height + " , " + tileWidth + ", " + tileHeight + ");" : "", 
+            "ajaxViewer.refresh('" + imgUrl + "', tileMap, false);"
+        };
+        
+        StringBuffer sb = new StringBuffer();
+        for(int i = 0; i < content.length; i++)
+            sb.append(content[i]);
+        
+        return sb.toString();
+    }
+    
+    //
+    // Helpers
+    //
+    private synchronized static int getNextClientId() {
+        return ++s_nextClientId;
+    }
+    
+    private void signalTileDirtyEvent() {
+        synchronized(tileDirtyEvent) {
+            dirtyFlag = true;
+            tileDirtyEvent.notifyAll();
+        }
+    }
+    
+    public void updateFrontEndActivityTime() {
+        lastFrontEndActivityTime = System.currentTimeMillis(); 
+    }
+
+    protected abstract FrameBufferCanvas getFrameBufferCavas();
+
+    public ConsoleProxyClientParam getClientParam() {
+        return clientParam;
+    }
+
+    public void setClientParam(ConsoleProxyClientParam clientParam) {
+        this.clientParam = clientParam;
+        ConsoleProxyPasswordBasedEncryptor encryptor = new ConsoleProxyPasswordBasedEncryptor(ConsoleProxy.getEncryptorPassword());
+        this.clientToken = encryptor.encryptObject(ConsoleProxyClientParam.class, clientParam);
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/b25122bd/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClientParam.java
----------------------------------------------------------------------
diff --git a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClientParam.java b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClientParam.java
index 8dc576f..8de4955 100644
--- a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClientParam.java
+++ b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClientParam.java
@@ -14,98 +14,97 @@
 // KIND, either express or implied.  See the License for the
 // specific language governing permissions and limitations
 // under the License.
-package com.cloud.consoleproxy;
-
-/**
- * 
- * @author Kelven Yang
- * Data object to store parameter info needed by client to connect to its host
- */
-public class ConsoleProxyClientParam {
-	
-	private String clientHostAddress;
-	private int clientHostPort; 
-	private String clientHostPassword;
-	private String clientTag;
-	private String ticket;
-	
-	private String clientTunnelUrl;
-	private String clientTunnelSession;
-	
-	private String ajaxSessionId;
-	
-	public ConsoleProxyClientParam() {
-		clientHostPort = 0;
-	}
-
-	public String getClientHostAddress() {
-		return clientHostAddress;
-	}
-
-	public void setClientHostAddress(String clientHostAddress) {
-		this.clientHostAddress = clientHostAddress;
-	}
-
-	public int getClientHostPort() {
-		return clientHostPort;
-	}
-
-	public void setClientHostPort(int clientHostPort) {
-		this.clientHostPort = clientHostPort;
-	}
-
-	public String getClientHostPassword() {
-		return clientHostPassword;
-	}
-
-	public void setClientHostPassword(String clientHostPassword) {
-		this.clientHostPassword = clientHostPassword;
-	}
-
-	public String getClientTag() {
-		return clientTag;
-	}
-
-	public void setClientTag(String clientTag) {
-		this.clientTag = clientTag;
-	}
-
-	public String getTicket() {
-		return ticket;
-	}
-
-	public void setTicket(String ticket) {
-		this.ticket = ticket;
-	}
-	
-	public String getClientTunnelUrl() {
-		return clientTunnelUrl;
-	}
-
-	public void setClientTunnelUrl(String clientTunnelUrl) {
-		this.clientTunnelUrl = clientTunnelUrl;
-	}
-
-	public String getClientTunnelSession() {
-		return clientTunnelSession;
-	}
-
-	public void setClientTunnelSession(String clientTunnelSession) {
-		this.clientTunnelSession = clientTunnelSession;
-	}
-	
-	public String getAjaxSessionId() {
-		return this.ajaxSessionId;
-	}
-	
-	public void setAjaxSessionId(String ajaxSessionId) {
-		this.ajaxSessionId = ajaxSessionId;
-	}
-
-	public String getClientMapKey() {
-		if(clientTag != null && !clientTag.isEmpty())
-			return clientTag;
-		
-		return clientHostAddress + ":" + clientHostPort;
-	}
-}
+package com.cloud.consoleproxy;
+
+/**
+ * 
+ * Data object to store parameter info needed by client to connect to its host
+ */
+public class ConsoleProxyClientParam {
+    
+    private String clientHostAddress;
+    private int clientHostPort; 
+    private String clientHostPassword;
+    private String clientTag;
+    private String ticket;
+    
+    private String clientTunnelUrl;
+    private String clientTunnelSession;
+    
+    private String ajaxSessionId;
+    
+    public ConsoleProxyClientParam() {
+        clientHostPort = 0;
+    }
+
+    public String getClientHostAddress() {
+        return clientHostAddress;
+    }
+
+    public void setClientHostAddress(String clientHostAddress) {
+        this.clientHostAddress = clientHostAddress;
+    }
+
+    public int getClientHostPort() {
+        return clientHostPort;
+    }
+
+    public void setClientHostPort(int clientHostPort) {
+        this.clientHostPort = clientHostPort;
+    }
+
+    public String getClientHostPassword() {
+        return clientHostPassword;
+    }
+
+    public void setClientHostPassword(String clientHostPassword) {
+        this.clientHostPassword = clientHostPassword;
+    }
+
+    public String getClientTag() {
+        return clientTag;
+    }
+
+    public void setClientTag(String clientTag) {
+        this.clientTag = clientTag;
+    }
+
+    public String getTicket() {
+        return ticket;
+    }
+
+    public void setTicket(String ticket) {
+        this.ticket = ticket;
+    }
+    
+    public String getClientTunnelUrl() {
+        return clientTunnelUrl;
+    }
+
+    public void setClientTunnelUrl(String clientTunnelUrl) {
+        this.clientTunnelUrl = clientTunnelUrl;
+    }
+
+    public String getClientTunnelSession() {
+        return clientTunnelSession;
+    }
+
+    public void setClientTunnelSession(String clientTunnelSession) {
+        this.clientTunnelSession = clientTunnelSession;
+    }
+    
+    public String getAjaxSessionId() {
+        return this.ajaxSessionId;
+    }
+    
+    public void setAjaxSessionId(String ajaxSessionId) {
+        this.ajaxSessionId = ajaxSessionId;
+    }
+
+    public String getClientMapKey() {
+        if(clientTag != null && !clientTag.isEmpty())
+            return clientTag;
+        
+        return clientHostAddress + ":" + clientHostPort;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-cloudstack/blob/b25122bd/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClientStatsCollector.java
----------------------------------------------------------------------
diff --git a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClientStatsCollector.java b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClientStatsCollector.java
index 82bceaf..15cf451 100644
--- a/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClientStatsCollector.java
+++ b/console-proxy/src/com/cloud/consoleproxy/ConsoleProxyClientStatsCollector.java
@@ -14,76 +14,75 @@
 // 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.OutputStreamWriter;
-import java.util.ArrayList;
-import java.util.Enumeration;
-import java.util.Hashtable;
-
-import com.google.gson.Gson;
-import com.google.gson.GsonBuilder;
-
-/**
- * 
- * @author Kelven Yang
- * ConsoleProxyClientStatsCollector collects client stats for console proxy agent to report
- */
-public class ConsoleProxyClientStatsCollector {
-	
-	ArrayList<ConsoleProxyConnection> connections;
-	
-	public ConsoleProxyClientStatsCollector() {
-	}
-	
-	public ConsoleProxyClientStatsCollector(Hashtable<String, ConsoleProxyClient> connMap) {
-		setConnections(connMap);
-	}
-	
-	public String getStatsReport() {
-		Gson gson = new GsonBuilder().setPrettyPrinting().create();
-		return gson.toJson(this);
-	}
-	
-	public void getStatsReport(OutputStreamWriter os) {
-		Gson gson = new GsonBuilder().setPrettyPrinting().create();
-		gson.toJson(this, os);
-	}
-
-	private void setConnections(Hashtable<String, ConsoleProxyClient> connMap) {
-		
-		ArrayList<ConsoleProxyConnection> conns = new ArrayList<ConsoleProxyConnection>();
-		Enumeration<String> e = connMap.keys();
-	    while (e.hasMoreElements()) {
-	    	synchronized (connMap) {
-	    		String key = e.nextElement();
-		        ConsoleProxyClient client = connMap.get(key);
-		         
-		        ConsoleProxyConnection conn = new ConsoleProxyConnection();
-		         
-		        conn.id = client.getClientId();
-		        conn.clientInfo = "";
-		        conn.host = client.getClientHostAddress();
-		        conn.port = client.getClientHostPort();
-		        conn.tag = client.getClientTag();
-		        conn.createTime = client.getClientCreateTime();
-		        conn.lastUsedTime = client.getClientLastFrontEndActivityTime();
-		        conns.add(conn);
-	    	}
-	    }
-	    connections = conns;
-	}
-	
-	public static class ConsoleProxyConnection {
-		public int id;
-		public String clientInfo;
-		public String host;
-		public int port;
-		public String tag;
-		public long createTime;
-		public long lastUsedTime;
-		
-		public ConsoleProxyConnection() {
-		}
-	}
-}
+package com.cloud.consoleproxy;
+
+import java.io.OutputStreamWriter;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.Hashtable;
+
+import com.google.gson.Gson;
+import com.google.gson.GsonBuilder;
+
+/**
+ * 
+ * ConsoleProxyClientStatsCollector collects client stats for console proxy agent to report
+ */
+public class ConsoleProxyClientStatsCollector {
+    
+    ArrayList<ConsoleProxyConnection> connections;
+    
+    public ConsoleProxyClientStatsCollector() {
+    }
+    
+    public ConsoleProxyClientStatsCollector(Hashtable<String, ConsoleProxyClient> connMap) {
+        setConnections(connMap);
+    }
+    
+    public String getStatsReport() {
+        Gson gson = new GsonBuilder().setPrettyPrinting().create();
+        return gson.toJson(this);
+    }
+    
+    public void getStatsReport(OutputStreamWriter os) {
+        Gson gson = new GsonBuilder().setPrettyPrinting().create();
+        gson.toJson(this, os);
+    }
+
+    private void setConnections(Hashtable<String, ConsoleProxyClient> connMap) {
+        
+        ArrayList<ConsoleProxyConnection> conns = new ArrayList<ConsoleProxyConnection>();
+        Enumeration<String> e = connMap.keys();
+        while (e.hasMoreElements()) {
+            synchronized (connMap) {
+                String key = e.nextElement();
+                ConsoleProxyClient client = connMap.get(key);
+                 
+                ConsoleProxyConnection conn = new ConsoleProxyConnection();
+                 
+                conn.id = client.getClientId();
+                conn.clientInfo = "";
+                conn.host = client.getClientHostAddress();
+                conn.port = client.getClientHostPort();
+                conn.tag = client.getClientTag();
+                conn.createTime = client.getClientCreateTime();
+                conn.lastUsedTime = client.getClientLastFrontEndActivityTime();
+                conns.add(conn);
+            }
+        }
+        connections = conns;
+    }
+    
+    public static class ConsoleProxyConnection {
+        public int id;
+        public String clientInfo;
+        public String host;
+        public int port;
+        public String tag;
+        public long createTime;
+        public long lastUsedTime;
+        
+        public ConsoleProxyConnection() {
+        }
+    }
+}