/**********************************************************************
   $Author: csanford $
   $Date: 2008/04/16 16:05:24 $
   $Revision: 1.4 $


   Copyright 2001 - 2004. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/

/// <summary>
/// Browsercaps object is a semi-featured browser detection object.  Because 
/// the Surgient browser matrix is limited, this does not include excessive 
/// detail.  When this script is loaded a single, global instance of Browsercaps
/// is created per page:  var browsercaps = new Browsercaps();
/// </summary>
function Browsercaps(){
    /// <summary>
    /// Navigator name constants
    /// </summary>
    this.OPERA = "Opera";
    this.SAFARI = "Safari";
    this.KONQUEROR = "Konqueror";
    this.IE = "Microsoft Internet Explorer";
    this.MOZ = "Mozilla";
    this.FIREFOX = "Firefox";
    this.NAN = "Unknown Browser";

    /// <summary>
    /// useragent and browser objects
    /// </summary>
    this.ua = navigator.userAgent.toLowerCase();
    this.browser = null;

    /// <summary>
    /// browser engine name settings
    /// </summary>
    this.isGecko       = (this.ua.indexOf('gecko') != -1 && this.ua.indexOf('safari') == -1);
    this.isAppleWebKit = (this.ua.indexOf('applewebkit') != -1);

    /// <summary>
    /// platform settings
    /// </summary>
    this.isWin    = (this.ua.indexOf('win') != -1);
    this.isWin32  = (this.isWin && ( this.ua.indexOf('95') != -1 || this.ua.indexOf('98') != -1 || this.ua.indexOf('nt') != -1 || this.ua.indexOf('win32') != -1 || this.ua.indexOf('32bit') != -1 || this.ua.indexOf('xp') != -1) );
    this.isMac    = (this.ua.indexOf('mac') != -1);
    this.isUnix   = (this.ua.indexOf('unix') != -1 || this.ua.indexOf('sunos') != -1 || this.ua.indexOf('bsd') != -1 || this.ua.indexOf('x11') != -1);
    this.isLinux  = (this.ua.indexOf('linux') != -1);

    /// <summary>
    /// platform version settings
    /// </summary>
    this.isVista  = (this.isWin && (this.ua.indexOf('nt 6') != -1));

    /// <summary>
    /// browser app settings
    /// </summary>
    this.isOp=(this.ua.indexOf('opera')!=-1);
    this.isSaf=(this.ua.indexOf('safari')!=-1);
    this.isKonq=(!this.isSaf && (this.ua.indexOf('konqueror')!=-1) ) ? true : false;
    this.isMoz=( (!this.isSaf && !this.isKonq ) && ( this.ua.indexOf('gecko')!=-1 ) ) ? true : false;
    this.isIe=((this.ua.indexOf('msie')!=-1)&&!this.isOp);

    if (this.isOp)
    {
        this.browser = this.OPERA;
    }
    else if (this.isSaf)
    {
        this.browser = this.SAFARI;
    }
    else if (this.isKonq)
    {
        this.browser = this.KONQUEROR;
    }
    else if (this.isIe)
    {
        this.browser = this.IE;
    }
    else if (this.isMoz)
    {
        if(this.ua.indexOf('firefox') != -1){
            this.browser = this.FIREFOX;
        } else {
            this.browser = this.MOZ;
        }
    }
    else {
        this.browser = this.NAN;
    }
}

var browsercaps = new Browsercaps();



/**********************************************************************
   $Author: greynold $
   $Date: 2007/01/16 00:09:32 $
   $Revision: 1.8 $


   Copyright 2001 - 2004. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/

/// <summary>
/// LogLevel struct defines the available levels for logging in the 
/// Surgient javascript logger.
/// </summary>
LogLevel = {
    DEBUG : 1,
    INFO : 2,
    WARN : 3,
    ERROR : 4,
    FATAL : 5,
    NONE : 6
};

/// <summary>
/// Static factory class for instantiating a Log object using the available
/// logging approaches, including alert boxes, DOM injection, etc.
/// Retrieving a Log instance of the type specifies automatically overrides the 
/// Log.log virtual method with the function defined in the getXLogger factory 
/// method.  The actual log() implementations are contained in the LogFactory
/// class, not the Log class.
/// </summary>
LogFactory = {
    
    getLogger: function(logLevel, prefix){
        var log = new Log(logLevel, prefix);
        // define the virtual function for the DefaultLogger
        log.log = function(msg, level, obj){
            //window.status = level + ":  " + msg;
        }
        log.printLog = function(){
            var win = window.open("about:blank", "_dWin", "height=600,width=400,toolbar=no,location=no,menubar=no,scrollbars=yes,resizable=yes");
            win.document.open();
            win.document.writeln("<html><head><title>Surgient Log</title></head><body><h3>Surgient Client Log</h3><pre>");
            // clean the _logMsgs of any html tags
            this._logMsgs = this._logMsgs.replace(/</g, "&lt;");
            this._logMsgs = this._logMsgs.replace(/>/g, "&gt;");
            win.document.writeln(this._logMsgs);
            win.document.writeln("</pre></body></html>");
            win.document.close();
        }
        return log;
    },

    getAlertLogger: function(logLevel, prefix) {
        var log = new Log(logLevel, prefix);
        // define the virtual function for the AlertLogger
        log.log = function(msg, level, obj){
            alert(level + ":  " + msg);
        }
        log.printLog = function(){
            alert("log dump: \n" + this._logMsgs);
        }
        return log;
    },

    getWriteLogger: function(logLevel, prefix) {
        var log = new Log(logLevel, prefix);
        // define the virtual function for the WriteLogger
        log.log = function(msg, level, obj) {
            document.writeln(level + ":&nbsp;&nbsp;" + msg + "<br/>");
        }
        log.printLog = function(){return;}
        return log;
    },

    getConsoleLogger: function(logLevel, prefix){
        var log = new Log(logLevel, prefix);
        // define the virtual function for the ConsoleLogger
        log.log = function(msg, level, obj) {
            if (window.console) {
                window.console.log(level + ":  " + msg);
            } else {
                alert(level + ":  " + msg);
            }
        }
        return log;
    }
};




/// <summary>
/// Logging class for Javascript.
/// </summary>
function Log(minLogLevel, logPrefix){

/// region : private fields -----------------------------------------
    this._logMsgs = "";
    this._currentLevel = minLogLevel;
    this._prefix = false;
    // assign the prefix a value if provided via the constructor
    if(typeof(logPrefix) != 'undefined'){ this._prefix = logPrefix; }

/// region : Virtual Methods ----------------------------------------
    /// <summary>
    /// Virtual method for logging.  This is dynamically assigned by the LogFactory
    /// when the desired implementation is specified.  The method override is guaranteed
    /// to follow this interface.
    /// </summary>
    /// <param type="string" name="msg">the message to log</param>
    /// <param type="LogLevel" name="level">the LogLevel for this message</param>
    /// <param type="object" name="obj">the originating Log object</param>
    this.log = null;

    /// <summary>
    /// Virtual method for dumping the contents of the log to some viewable/copyable source.  
    /// This is dynamically assigned by the LogFactory when the desired implementation is specified.  
    /// The method override is guaranteed to follow this interface.
    /// </summary>
    this.printLog = null;

/// region : Properties ---------------------------------------------

/// region : Methods ------------------------------------------------
    /// <summary>
    /// Appends log values to the internal string buffer.
    /// </summary>
    /// <param type="string" name="msg">the message to log</param>
    /// <param type="LogLevel" name="level">the LogLevel for this message</param>
    /// <param type="object" name="obj">the originating Log object</param>
    this._appendLog = _appendLog;
    function _appendLog(msg, level, obj){
        if(this._prefix != false){
            msg = this._prefix + " - " + msg;
        }
        this._logMsgs += new Date().toLocaleString() + " | " + level + " | " + msg + "\n";
        if(this.log != null){
            this.log(msg, level, obj);
        }
    }

    /// <summary>
    /// Takes a Javascript object and inspects it's properties turning that 
    /// into a string dump.
    /// </summary>
    this.dumpObject = _dumpObject;
    function _dumpObject(obj, indent){
        if (!indent) { indent="";}
        if (indent.length > 20) { return ; }
        var s="{\n";
        for (var p in obj) {
            s += indent + p + ":";
            var type = typeof(obj[p]);
            type = type.toLowerCase();
            if (type == 'object') {
                s += this.dumpObject(obj[p], indent + "----");
            } else {
                s += obj[p];
            }
            s += "\n";
        }
        s += indent + "}";
        return s;
    }

    /// <summary>
    /// Clears the current log buffer of all messages.
    /// </summary>
    this.clearLog = _clearLog;
    function _clearLog(){
        this._logMsgs = "";
    }

    /// <summary>
    /// Returns the current value of the log buffer.
    /// </summary>
    this.getLog = _getLog;
    function _getLog(){
        return this._logMsgs;
    }

    /// <summary>
    /// Logs the message at the LogLevel.DEBUG level.
    /// </summary>
    /// <param type="string" name="msg">the message to log</param>
    this.debug = _debug;
    function _debug(msg){
        if(this._currentLevel <= LogLevel.DEBUG){
           this._appendLog(msg, "Debug", this);
        }
    }

    /// <summary>
    /// Logs the message at the LogLevel.INFO level.
    /// </summary>
    /// <param type="string" name="msg">the message to log</param>
    this.info = _info;
    function _info(msg){
        if(this._currentLevel <= LogLevel.INFO){
            this._appendLog(msg, "Info", this);
        }
    }

    /// <summary>
    /// Logs the message at the LogLevel.WARN level.
    /// </summary>
    /// <param type="string" name="msg">the message to log</param>
    this.warn = _warn;
    function _warn(msg){
        if(this._currentLevel <= LogLevel.WARN){
            this._appendLog(msg, "Warning", this);
        }
    }

    /// <summary>
    /// Logs the message at the LogLevel.ERROR level.
    /// </summary>
    /// <param type="string" name="msg">the message to log</param>
    this.error = _error;
    function _error(msg){
        if(this._currentLevel <= LogLevel.ERROR){
            this._appendLog(msg, "Error", this);
        }
    }

    /// <summary>
    /// Logs the message at the LogLevel.FATAL level.
    /// </summary>
    /// <param type="string" name="msg">the message to log</param>
    this.fatal = _fatal;
    function _fatal(msg){
        if(this._currentLevel <= LogLevel.FATAL){
            this._appendLog(msg, "Fatal", this);
        }
    }
}

// define the default log, this can be overridden by implementors, but
// it guarantees that a logging instance is available to all URA code
var log = LogFactory.getLogger(LogLevel.DEBUG);

// bind the printLog() method to a keyboard hotkey CTRL + SHIFT + L so that 
// the log can be printed easily on the client
function logKeyPressHandler(evt){
	var shift = false;
	var ctrl = false;
	(evt.ctrlKey || evt.ctrlLeft)? ctrl = true : ctrl = false;
	(evt.shiftKey || evt.shiftLeft)? shift = true : shift = false;

	if(shift && ctrl){
		var code = 0;
		if(typeof(evt.charCode) != "undefined"){
			code = evt.charCode;
		} else {
			code = evt.keyCode;
		}
		if(code == 108 || code == 76 || code == 12){
			try{
                log.printLog();
            } catch (e){}
		}
	}
}

// attach the key events to the logger
try{
	document.attachEvent("onkeypress", logKeyPressHandler);
} catch(e){}

try{
	document.addEventListener("keypress", logKeyPressHandler, false);
} catch(e){}


/**********************************************************************
   $Author: greynold $
   $Date: 2007/06/08 22:38:06 $
   $Revision: 1.14 $


   Copyright 2001 - 2007. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/
/// Verify the existence of the appPath variable.  If it has not been set,
/// create it and specify the default path which is the virtual directory: /URA
if(typeof(appPath) == "undefined"){
    window["appPath"] = "/URA";
}

/// <summary>
/// ControlPlatform struct defines the available deployment platforms for the 
/// controls in URA.
/// </summary>
ControlPlatform = {
    /// <summary>
    /// Sets the control as an ActiveX control.
    /// </summary>
    ActiveX : 0,
    /// <summary>
    /// Sets the control as a Java Applet.
    /// </summary>
    Applet : 1
};

/// <summary>
/// TermClientType struct defines the available terminal clients available in 
/// URA.
/// </summary>
TermClientType = {
    /// <summary>
    /// Sets the control as an RDP terminal client.
    /// </summary>
    RDP : 0,
    /// <summary>
    /// Sets the control as a VNC terminal client.
    /// </summary>
    VNC : 1,
    /// <summary>
    /// Sets the control as a Citrix terminal client.
    /// </summary>
    Citrix : 2,
    /// <summary>
    /// Sets the control as a MvsConsole terminal client.
    /// </summary>
    MvsConsole : 3,
    /// <summary>
    /// Sets the control as a VmcConsole terminal client.
    /// </summary>
    VmcConsole : 4,
    /// <summary>
    /// Sets the control as a RDPShadowing terminal client.
    /// </summary>
    RDPShadowing : 5,
    /// <summary>
    /// Sets the control as a Esx3Console terminal client.
    /// </summary>
    Esx3Console : 6
};

/// <summary>
/// TermClientProtocol defines the protocol schemes for the terminal clients 
/// available in URA.
/// </summary>
TermClientProtocol = {
    /// <summary>
    /// Sets the RDP protocol scheme.
    /// </summary>
    RDP : "rdp",
    /// <summary>
    /// Sets the VNC protocol scheme.
    /// </summary>
    VNC : "vnc",
    /// <summary>
    /// Sets the Citrix protocol scheme.
    /// </summary>
    Citrix : "citrix",
    /// <summary>
    /// Sets the MvsConsole protocol scheme.
    /// </summary>
    MvsConsole : "vmrc",
    /// <summary>
    /// Sets the VmcConsole protocol scheme.
    /// </summary>
    VmcConsole : "vmx",
    /// <summary>
    /// Sets the Esx3Console protocol scheme.
    /// </summary>
    Esx3Console : "vmx"
};

/// <summary>
/// TunnelConfigType struct defines the available tunnel configuration types 
/// available in URA.
/// </summary>
TunnelConfigType = {
    /// <summary>
    /// Sets the control to use HTTP to tunnel to the URA Gateway.
    /// </summary>
    HTTPTunnel : 0,
    /// <summary>
    /// Sets the control to use HTTPS to tunnel to the URA Gateway.
    /// </summary>
    HTTPSTunnel : 1,
    /// <summary>
    /// Sets the control to act as a communication endpoint.  This setting does not 
    /// tunnel to the URA Gateway.
    /// </summary>
    NoOpTunnel : 2,
    /// <summary>
    /// Sets the control to reverse proxy through the URA Gateway.
    /// </summary>
    SocketProxy : 3
};

/// <summary>
/// HostType struct defines the virtualization platforms available to the system.
/// </summary>
HostType = {
    /// <summary>
    /// Sets the type to MVS.
    /// </summary>
    MVS_VM : "MVS Virtual Machine",
    /// <summary>
    /// Sets the type to ESX.
    /// </summary>
    ESX_VM : "ESX Virtual Machine",
    /// <summary>
    /// Sets the type to ESX3.
    /// </summary>
    ESX3_VM : "ESX3 Virtual Machine",
    /// <summary>
    /// Sets the type to GSX.
    /// </summary>
    GSX_VM : "GSX Virtual Machine"
};

/// <summary>
/// URAConfigSetting is a object that contains the control platform, terminal client
/// type, and tunnel configuration type settings for the URA Coordinator to use when 
/// instantiating the objects needed to set up URA communication.
/// </summary>
/// <param name="controlPlatform">the <see cref="ControlPlatform"/> setting to use</param>
/// <param name="termClientType">the <see cref="TermClientType"/> setting to use</param>
/// <param name="tunnelConfigType">the <see cref="TunnelConfigType"/> setting to use</param>
/// <param name="hostAddress">the host IPAddress to use</param>
/// <param name="hostPort">the host port number to use</param>
function URAConfigSetting( controlPlatform, termClientType, tunnelConfigType, hostAddress, hostPort ){

/// region : Properties ---------------------------------------------
    /// <summary>
    /// Gets/sets the <see cref="ControlPlatform"/> of this URAConfigSetting.
    /// </summary>
    this.ControlPlatform = controlPlatform;

    /// <summary>
    /// Gets/sets the <see cref="TermClientType"/> of this URAConfigSetting.
    /// </summary>
    this.TermClientType = termClientType;


    /// <summary>
    /// Gets/sets the <see cref="TunnelConfigType"/> of this URAConfigSetting.
    /// </summary>
    this.TunnelConfigType = tunnelConfigType;

    /// <summary>
    /// Gets/sets the IPAddress of the host to which this URAConfigSetting applies.
    /// </summary>
    this.HostAddress = hostAddress;

    /// <summary>
    /// Gets/sets the port number of the host to which this URAConfigSetting applies.
    /// </summary>
    this.HostPort = hostPort;
}

/// <summary>
/// BaseObject is the base class for all Surgient objects.  It contains the methods to get 
/// and raise events.
/// </summary>
function BaseObject(id){

    /// <summary>
    /// Gets/sets the Id for this object.
    /// </summary>
    this.Id = id;

    // private properties
    this._timeout = null;
    this._interval = null;

    /// <summary>
    /// Private, generic method to raise events by invoking them as methods on the object.  If 
    /// no event handler is provided, this method fails silently.
    /// </summary>
    /// <param name="evt" type="string">name of the event to raise</param>
    /// <param name="args" type="string">args for this event</param>
    this._raiseEvent = _raiseEvent;
    function _raiseEvent(evt, args){
        if(args != null && args != ""){
            args = args.replace(/\r\n/gi, "");
        }
        if(this[evt] != null){
            var statement = this[evt] + "(this, '" + args + "');";
            eval(statement);
        }
    }

    /// <summary>
    /// Convenience method to return a handle to a instance method.
    /// </summary>
    /// <param name="event" type="string">name of the event to attach</param>
    this._getHandler = _getHandler;
    function _getHandler(handler){
        return this.Id + "." + handler;
    }

    /// <summary>
    /// Convenience method to return a handle to a instance method.
    /// </summary>
    this.getClass = _getClass;
    function _getClass(){
        var constr = this.constructor;
		var re = /function\s*(\w+)\s*\(+/;
		re.exec(constr);
        return RegExp.$1;
    }

    /// <summary>
    /// Convenience wrapper around the Error object constructor which does not allow 
    /// for the message property to be set as a constructor argument.
    /// </summary>
    /// <param name="msg" type="string">the message for the Error</param>
    this._newError = _newError;
    function _newError(msg){
        var er = new Error();
        er.message = msg;
        return er;
    }

    /// <summary>
    /// Private method for setting up a timeout for this object including the 
    /// mechanism to retain a pointer to the timeout object for future cancellation.
    /// </summary>
    /// <param name="func" type="string">the function to execute in the timeout</param>
    /// <param name="wait" type="integer">the interval in milliseconds to wait before executing the timeout</param>
    this._setTimeout = _setTimeout;
    function _setTimeout(func, wait){
        this._cancelTimeout();
        this._timeout = window.setTimeout(func, wait);
    }

    /// <summary>
    /// Private method for cancelling any timeout callbacks set up by this object.
    /// </summary>
    this._cancelTimeout = _cancelTimeout;
    function _cancelTimeout(){
        if(this._timeout != null){
            window.clearTimeout(this._timeout);
        }
        this._timeout = null;
    }

    /// <summary>
    /// Private method for setting up an interval for this object including the 
    /// mechanism to retain a pointer to the interval object for future cancellation.
    /// </summary>
    /// <param name="func" type="string">the function to execute in the interval</param>
    /// <param name="wait" type="integer">the interval in milliseconds to wait</param>
    this._setInterval = _setInterval;
    function _setInterval(func, wait){
        if(this._interval != null){
            this._cancelInterval();
        }
        this._interval = window.setInterval(func, wait);
    }

    /// <summary>
    /// Private method for cancelling any interval callbacks set up by this object.
    /// </summary>
    this._cancelInterval = _cancelInterval ;
    function _cancelInterval (){
        if(this._interval != null){
            window.clearInterval(this._interval);
        }
        this._interval = null;
    }
}


/**********************************************************************
   $Author: dbabbitt $
   $Date: 2006/02/14 21:11:39 $
   $Revision: 1.2 $


   Copyright 2001 - 2004. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/

/// <summary>
/// URAExceptionType struct defines the available Exception error 
/// codes in URA.
/// </summary>
URAExceptionType = {
    /// <summary>
    /// Error code when the TunnelConfigFactory cannot find a matching 
    /// TunnelConfig for the requested values.
    /// </summary>
    InvalidTunnelConfig : 0,
    /// <summary>
    /// Error code when the TermClientFactory cannot find a matching 
    /// TermClient for the requested values.
    /// </summary>
    InvalidTermClient : 1,
    /// <summary>
    /// Error code when an element with the same key already exists in the collection.
    /// </summary>
    ArgumentException : 2
};

/// <summary>
/// URAException is the base Exception object used in the URA script code.
/// </summary>
/// <param name="message">the message for the exception</param>
/// <param name="exceptionType">the <see cref="URAExceptionType"/> setting to use</param>
function URAException(message, exceptionType){

/// region : Properties ---------------------------------------------
    /// <summary>
    /// Gets/sets the message of this exception.
    /// </summary>
    this.Message = message;

    /// <summary>
    /// Gets/sets the <see cref="URAExceptionType"/> of this exception.
    /// </summary>
    this.getExceptionType = exceptionType;
}


/**********************************************************************
   $Author: csanford $
   $Date: 2008/08/06 22:13:34 $
   $Revision: 1.18 $


   Copyright 2001 - 2004. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/
/// <summary>
/// TerminalClientSettings struct defines the values for shared TerminalClient settings 
/// which are managed via global configuration.
/// </summary>
TerminalClientSettings = {
    /// <summary>
    /// Sets the ColorDepth for controls as an integer.
    /// </summary>
    ColorDepth : 24,
    /// <summary>
    /// Enables/disables sound in the TerminalClient.
    /// </summary>
    EnableSound : false,
    /// <summary>
    /// Enables/disables opening the TerminalClient in full screen mode.
    /// </summary>
    EnableFullScreen : false,
    /// <summary>
    /// Enables/disables drive mapping in the TerminalClient.
    /// </summary>
    EnableDriveMapping : false
};


/// <summary>
/// Abstract class for TermClient objects.
/// </summary>
function TermClient (id){
/// region : inheritance --------------------------------------------
    this.base = BaseObject;
    this.base(id);

/// region : private fields -----------------------------------------
    this._control = null; // holds a reference to the HTML element
    this._connectCount = 0; // counter for the number of permissable connection attempts
    this._hostURL = ""; // holds the complete URL for the host
    this._isErrorState = false; // eliminates repetitive OnConnecErrors from ActiveX & Applet controls

/// region : Properties ---------------------------------------------
    /// <summary>
    /// Gets/sets the Protocol for this object.
    /// </summary>
    this.Protocol = "";

    /// <summary>
    /// Gets/sets the ControlPlatform for this object.
    /// </summary>
    this.Platform = "";

    /// <summary>
    /// Gets/sets the TermClientType for this object.
    /// </summary>
    this.TermClientType = "";

    /// <summary>
    /// Gets/sets the host IP address for this object.
    /// </summary>
    this.HostAddress = "";

    /// <summary>
    /// Gets/sets the destination port for this object.
    /// </summary>
    this.HostPort = "";

    /// <summary>
    /// Gets/sets the vm name for this object.
    /// </summary>
    this.VmName = "";

    /// <summary>
    /// Gets/sets the vm file for this object.
    /// </summary>
    this.VmFile = "";

    /// <summary>
    /// Gets/sets the width setting for this object.
    /// </summary>
    this.Width = 0;

    /// <summary>
    /// Gets/sets the height setting for this object.
    /// </summary>
    this.Height = 0;

    /// <summary>
    /// Gets/sets the HTML element reference this TermClient instance is loaded in.
    /// </summary>
    this.Element = null;

    /// <summary>
    /// Gets/sets the Username to use when connecting to this TermClient host.
    /// </summary>
    this.Username = "";

    /// <summary>
    /// Gets/sets the Password to use when connecting to this TermClient host.
    /// </summary>
    this.Password = "";

    /// <summary>
    /// Gets/sets the Username required to authenticate via the TermClient's protocol.
    /// </summary>
    this.ProtocolUsername = "";

    /// <summary>
    /// Gets/sets the Password required to authenticate via the TermClient's protocol.
    /// </summary>
    this.ProtocolPassword = "";

    /// <summary>
    /// Gets/sets the Password required to authenticate on the vm's Host.
    /// </summary>
    this.HostUsername = "";

    /// <summary>
    /// Gets/sets the Password required to authenticate on the vm's Host.
    /// </summary>
    this.HostPassword = "";

    /// <summary>
    /// Gets/sets the Password required to authenticate on the vm's Host.
    /// </summary>
    this.HostType = "";

    /// <summary>
    /// Gets/sets the version of the virtualization platform on the vm's Host.
    /// </summary>
    this.HostVersion = "";

/// region : Methods ------------------------------------------------
    /// <summary>
    /// Noop alerts the user that the calling method has not been implemented by the class.
    /// </summary>
    /// <param name="configSettings">array of <see cref="URAConfigSetting"/> settings to use</param>
    function _noop(caller){
        alert(caller + ' method must be overridden by implementing class');
    }

    /// <summary>
    /// Method handles any initialization needed for the control before the connect() method 
    /// is called.  Not all controls will implement the init() method therefore this is not 
    /// a "virtual" method, just an empty stub that must be overridden for any effect to occur.
    /// </summary>
    /// <param name="args" type="object">basic arguments, this is dependent upon implementation</param>
    this.init = _init;
    function _init(args){
        // no noop call here, if a control does not override, fail silently.
        return;
    }

    /// <summary>
    /// Method tells the TermClient to attempt to start the remote session. Raises 
    /// an OnConnect event.
    /// </summary>
    this.connect = _connect;
    function _connect(){
        _noop('connect()');
    }

    /// <summary>
    /// Method tells the TermClient to attempt to disconnect from the remote session.
    /// </summary>
    this.disconnect = _disconnect;
    function _disconnect(args) {
        _noop('disconnect()');
    }

    /// <summary>
    /// Method renders the TermClient's HTML to the target frame's document.  The method 
    /// of render varies for each implementation.
    /// </summary>
    this.renderHtml = _renderHtml;
    function _renderHtml() {
        _noop('renderHtml()');
    }

    /// <summary>
    /// Method gets the ActiveX or Applet control of the TermClient depending upon what 
    /// ControlPlatform has been deployed.
    /// </summary>
    /// <return type="object">the internal control, if this control has not been properly
    /// initialized this method ***can return null***</return>
    this.getControl = _getControl;
    function _getControl(){
        return this._control;
    }

    /// <summary>
    /// Method determines if the control is actually connected or not, helpful for polling 
    /// exercises and error checking in the URACoordinators.
    /// </summary>
    this.isConnected = _isConnected;
    function _isConnected(){
        _noop('isConnected()');
    }

    /// <summary>
    /// Method to send Ctrl+Alt+Delete to the TermClient control
    /// </summary>
    this.sendCtrlAltDelete = _sendCtrlAltDelete;
    function _sendCtrlAltDelete(){
        _noop('sendCtrlAltDelete()');
    }

    /// <summary>
    /// Method to retrieve the key commands to send Ctrl+Alt+Delete to the TermClient control.
    /// </summary>
    this.getCADCommand = _getCADCommand;
    function _getCADCommand(){
        _noop('getCADCommand');
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnConnect event.
    /// </summary>
    this.controlConnectHandler = _controlConnectHandler;
    function _controlConnectHandler(){
        _noop('controlConnectHandler');
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnDisconnect event.
    /// </summary>
    this.controlDisconnectHandler = _controlDisconnectHandler;
    function _controlDisconnectHandler(){
        _noop('controlDisconnectHandler');
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnConnectError event.
    /// </summary>
    this.controlConnectErrorHandler = _controlConnectErrorHandler;
    function _controlConnectErrorHandler(){
        _noop('controlConnectErrorHandler');
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnAutoReconnecting event.
    /// </summary>
    this.controlAutoReconnectingHandler = _controlAutoReconnectingHandler;
    function _controlAutoReconnectingHandler(){
        _noop('controlAutoReconnectingHandler');
    }

/// region : Event Delegates ----------------------------------------
    /// <summary>
    /// Event delegate for the Connect event.
    /// </summary>
    /// <param name="sender" type="object">this object</param>
    /// <param name="args" type="object">any event arguments for this object</param>
    this.OnConnect = null;

    /// <summary>
    /// Event delegate for the ConnectError event.
    /// </summary>
    /// <param name="sender" type="object">this object</param>
    /// <param name="args" type="TermClientConnectErrorArgs">specific action to take, may be null</param>
    this.OnConnectError = null;

    /// <summary>
    /// Event delegate for the Disconnect event.
    /// </summary>
    /// <param name="sender" type="object">this object</param>
    /// <param name="args" type="object">any event arguments for this object</param>
    this.OnDisconnect = null;

    /// <summary>
    /// Event delegate for the OnLoadError event.
    /// </summary>
    /// <param name="sender" type="object">this object</param>
    /// <param name="args" type="object">any event arguments for this object</param>
    this.OnLoadError = null;

    /// <summary>
    /// Event delegate for the AutoReconnecting event.
    /// </summary>
    /// <param name="sender" type="object">this object</param>
    /// <param name="args" type="object">any event arguments for this object</param>
    this.OnAutoReconnecting = null;

    /// <summary>
    /// Event delegate for the CancelInterval event.  Used for working around the standard
    /// timeout implementation where necessary (i.e. RDP 6.1 ActiveX).
    /// </summary>
    /// <param name="sender" type="object">this object</param>
    /// <param name="args" type="object">any event arguments for this object</param>
    this.OnCancelInterval = null;
}

/// <summary>
/// Enumeration of actions to take when a TermClient raises the ConnectError
/// </summary>
TermClientConnectErrorArgs = {
    /// <summary>
    /// Make a connection attempt with the next configured TermClient, if any.
    /// This is the default value.
    /// </summary>
    TryNext : "TermClientConnectError_TryNext",
    /// <summary>
    /// Do not try the next configured TermClient.
    /// </summary>
    Abort : "TermClientConnectError_Abort"
};


/**********************************************************************
   $Author: greynold $
   $Date: 2006/03/09 21:04:22 $
   $Revision: 1.5 $


   Copyright 2001 - 2004. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/

/// <summary>
/// Abstract class for TunnelConfig objects.
/// </summary>
function TunnelConfig (id){
/// region : inheritance --------------------------------------------
    this.base = BaseObject;
    this.base(id);

/// region : private fields -----------------------------------------
    this._control = null; // holds a reference to the HTML element
    this._connection = null; // holds a reference to the connection object
    this._connectCount = 0; // counter for the number of permissable connection attempts
    this._verifyCount = 0; // counter for the number of connection verification attempts
    this._gatewayName = "/HTGateway/"; // default URL bit for the gateway server
    this._hostURL = ""; // holds the complete URL for the host
    this._gatewayURL = ""; // holds the complete URL for the gateway

/// region : Properties ---------------------------------------------

    /// <summary>
    /// Gets/sets the ControlPlatform for this object.
    /// </summary>
    this.Platform = null;

    /// <summary>
    /// Gets/sets the TunnelConfigType for this object.
    /// </summary>
    this.TunnelConfigType = null;

    /// <summary>
    /// Gets/sets the Gateway address for this object.
    /// </summary>
    this.GatewayAddress = "";

    /// <summary>
    /// Gets/sets the Gateway port for this TunnelConfig.
    /// </summary>
    this.GatewayPort = "";

    /// <summary>
    /// Gets/sets the Host address for this TunnelConfig.
    /// </summary>
    this.HostAddress = "";

    /// <summary>
    /// Gets/sets the Host port for this TunnelConfig.
    /// </summary>
    this.HostPort = "";

    /// <summary>
    /// Gets/sets the Host protocol scheme for this TunnelConfig.
    /// </summary>
    this.HostProtocol = "";

    /// <summary>
    /// Gets/sets the HTML element reference this TunnelConfig instance is loaded in.
    /// </summary>
    this.Element = null;
    
    /// <summary>
    /// Gets/sets the name of the class that handles the upstream encoding.  This must be one of the following
    /// values:  "" or a comma delimited list of:  "OctetStreamUpHandler", "MultipartFormUpHandler" , "Base64UpHandler"
    /// </summary>   
    this.UpsteamHandler = "OctetStreamUpHandler,MultipartFormUpHandler,Base64UpHandler";
    
    /// <summary>
    /// Gets/sets the name of the class that handles the downstream encoding.  This must be one of the following
    /// values:  "" or a comma delimited list of:  "OctetStreamDnHandler", "Base64DnHandler"
    /// </summary>  
    this.DownstreamHandler = "OctetStreamDnHandler,Base64DnHandler";

/// region : Methods ------------------------------------------------
    /// <summary>
    /// Noop alerts the user that the calling method has not been implemented by the class.
    /// </summary>
    /// <param name="configSettings">array of <see cref="URAConfigSetting"/> settings to use</param>
    function _noop(caller){
        alert(caller + ' method must be overridden by implementing class');
    }

    /// <summary>
    /// Private method to verify the TunnelConfig's connection before raising the OnConnect event.
    /// </summary>    
    this._verifyConnection = _verifyConnection;
    function _verifyConnection(){
        _noop("_verifyConnection()");
    }

    /// <summary>
    /// Method handles any initialization needed for the control before the connect() method 
    /// is called.  Not all controls will implement the init() method therefore this is not 
    /// a "virtual" method, just an empty stub that must be overridden for any effect to occur.
    /// </summary>
    /// <param name="args" type="object">basic arguments, this is dependent upon implementation</param>
    this.init = _init;
    function _init(args){
        // no noop call here, if a control does not override, fail silently.
        return;
    }

    /// <summary>
    /// Method tells the TunnelConfig to attempt to start the URA tunnel. Raises 
    /// an OnConnect event.
    /// </summary>
    this.connect = _connect;
    function _connect(){
        _noop('connect()');
    }

    /// <summary>
    /// Method tells the TunnelConfig to attempt to disconnect from the URA tunnel.
    /// </summary>
    this.disconnect = _disconnect;
    function _disconnect(args) {
        _noop('disconnect()');
    }

    /// <summary>
    /// Method called by the TunnelConfig instance when a connection error has occurred.  Raises 
    /// an OnConnectError event.
    /// </summary>
    this.connectError = _connectError;
    function _connectError(error) {
        _noop('connectError()');
    }

    /// <summary>
    /// Method renders the TunnelConfig's HTML to the target element's child nodes.  The method 
    /// of render varies for each implementation.
    /// </summary>
    this.renderHtml = _renderHtml;
    function _renderHtml() {
        _noop('renderHtml()');
    }

    /// <summary>
    /// Method gets the ActiveX or Applet control of the TunnelConfig depending upon what 
    /// ControlPlatform has been deployed.
    /// </summary>
    /// <return type="object">the internal control, if this control has not been properly
    /// initialized this method ***can return null***</return>
    this.getControl = _getControl;
    function _getControl(){
        return this._control;
    }

    /// <summary>
    /// Gets the local IPAddress of the TunnelConfig.
    /// </summary>
    /// <return type="string">the local IPAddress of the TunnelConfig</return>
    this.getDestinationIPAddress = _getDestinationIPAddress;
    function _getDestinationIPAddress() {
        _noop('getDestinationIPAddress()');
    }

    /// <summary>
    /// Gets the local Port of the TunnelConfig.
    /// </summary>
    this.getDestinationPort = _getDestinationPort;
    function _getDestinationPort() {
        _noop('getDestinationPort()');
    }

    /// <summary>
    /// Method determines if the control is actually connected or not, helpful for polling 
    /// exercises and error checking in the URACoordinators.
    /// </summary>
    this.isConnected = _isConnected;
    function _isConnected(){
        _noop('isConnected()');
    }

/// region : Event Delegates ----------------------------------------
    /// <summary>
    /// Event delegate for the Connect event.
    /// </summary>
    /// <param name="sender" type="object">this object</param>
    /// <param name="args" type="object">any event arguments for this object</param>
    this.OnConnect = null;

    /// <summary>
    /// Event delegate for the ConnectError event.
    /// </summary>
    /// <param name="sender" type="object">this object</param>
    /// <param name="args" type="object">any event arguments for this object</param>
    this.OnConnectError = null;

    /// <summary>
    /// Event delegate for the Disconnect event.
    /// </summary>
    /// <param name="sender" type="object">this object</param>
    /// <param name="args" type="object">any event arguments for this object</param>
    this.OnDisconnect = null;
    
    /// <summary>
    /// Event delegate for the LoadError event.
    /// </summary>
    /// <param name="sender" type="object">this object</param>
    /// <param name="args" type="object">any event arguments for this object</param>
    this.OnLoadError = null;
}


/**********************************************************************
   $Author: greynold $
   $Date: 2006/03/21 21:02:19 $
   $Revision: 1.3 $


   Copyright 2001 - 2004. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/

/// <summary>
/// Factory class for creating TermClient objects.
/// </summary>
/// <param name="id">Id for the control</param>
function TermClientFactory (id){

/// region : private fields -----------------------------------------
    this._termClients = new Array();


/// region : Properties ---------------------------------------------
    /// <summary>
    /// Gets/sets the Id for this object.
    /// </summary>
    this.Id = id;


/// region : Methods ------------------------------------------------
    /// <summary>
    /// Registers a <see cref="TermClient"/> implementation class with the factory under the 
    /// listed platform and TermClient types.
    /// </summary>
    /// <param name="platform">the <see cref="ControlPlatform"/> setting to use</param>
    /// <param name="termClientType">the <see cref="TermClientType"/> setting to use</param>
    /// <param name="className">the class name of the TermClient</param>
    this.registerTermClient = _registerTermClient;
    function _registerTermClient(platform, termClientType, className){
        var key = platform + "_" + termClientType;
        if(typeof(this._termClients[key]) == "undefined"){
            log.debug("[" + this.Id + "]:  registering TermClient: " + key + " as " + className);
            this._termClients[key] = className;
        } else {
            log.error("[" + this.Id + "]:  TermClientFactory failed to register object: " + key + " as: " + className);
            throw new URAException("Duplicate object for Platform: " + platform + " TermClientType: " + 
                termClientType + " className: " + className, URAExceptionType.ArgumentException);
        }
    }

    /// <summary>
    /// Attempts to instantiate an implementation of <see cref="TermClient"/> using the supplied 
    /// <see cref="TermClientType"/> and <see cref="ControlPlatform"/> types provided.
    /// </summary>
    /// <param name="termClientType">the <see cref="TermClientType"/> setting to use</param>
    /// <param name="platform">the <see cref="ControlPlatform"/> setting to use</param>
    this.getTermClient = _getTermClient;
    function _getTermClient(id, termClientType, platform){
        var key = platform + "_" + termClientType;
        var termClient = this._termClients[key];
        // try to instantiate the requested TunnelConfig
        try{
            eval("window." + id + " = new " + termClient + "('" + id + "');");
            return eval("window." + id);
        } catch (e){
            log.error("[" + this.Id + "]:  TermClientFactory failed to load object: " + key + " as: " + termClient);
            throw new URAException("No available TermClient for Type: " + 
                termClientType + " and Platform: " + platform, URAExceptionType.InvalidTermClient);
        }
    }
}

// create single, global instance of the TermClientFactory
var termClientFactory = new TermClientFactory("termClientFactory");


/**********************************************************************
   $Author: greynold $
   $Date: 2006/03/21 21:02:19 $
   $Revision: 1.3 $


   Copyright 2001 - 2004. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/

/// <summary>
/// Factory class for creating TunnelConfig objects.
/// </summary>
/// <param name="id">Id for the control</param>
function TunnelConfigFactory (id){

/// region : private fields -----------------------------------------
    this._tunnelConfigs = new Array();


/// region : Properties ---------------------------------------------
    /// <summary>
    /// Gets/sets the Id for this object.
    /// </summary>
    this.Id = id;


/// region : Methods ------------------------------------------------
    /// <summary>
    /// Registers a <see cref="TunnelConfig"/> implementation class with the factory under the 
    /// listed platform and TunnelConfig types.
    /// </summary>
    /// <param name="platform">the <see cref="ControlPlatform"/> setting to use</param>
    /// <param name="tunnelConfigType">the <see cref="TunnelConfigType"/> setting to use</param>
    /// <param name="className">the class name of the TunnelConfig</param>
    this.registerTunnelConfig = _registerTunnelConfig;
    function _registerTunnelConfig(platform, tunnelConfigType, className){
        var key = platform + "_" + tunnelConfigType;
        if(typeof(this._tunnelConfigs[key]) == "undefined"){
            this._tunnelConfigs[key] = className;
        } else {
            log.error("[" + this.Id + "]:  TunnelConfigFactory failed to register object: " + key + " as: " + className);
            throw new URAException("Duplicate object for Platform: " + platform + " TunnelConfigType: " + 
                tunnelConfigType + " className: " + className, URAExceptionType.ArgumentException);
        }
    }

    /// <summary>
    /// Attempts to instantiate an implementation of <see cref="TunnelConfig"/> using the supplied 
    /// <see cref="TunnelConfigType"/> and <see cref="ControlPlatform"/> types provided.
    /// </summary>
    /// <param name="tunnelConfigType">the <see cref="TunnelConfigType"/> setting to use</param>
    /// <param name="platform">the <see cref="ControlPlatform"/> setting to use</param>
    this.getTunnelConfig = _getTunnelConfig;
    function _getTunnelConfig(id, tunnelConfigType, platform){
        var key = platform + "_" + tunnelConfigType;
        var tunnelConfig = this._tunnelConfigs[key];
        // try to instantiate the requested TunnelConfig
        try{
            eval("window." + id + " = new " + tunnelConfig + "('" + id + "');");
            return eval("window." + id);
        } catch (e){
            log.error("[" + this.Id + "]:  TunnelConfigFactory failed to load object: " + key + " as: " + tunnelConfig);
            throw new URAException("No available TunnelConfig for Type: " + 
                tunnelConfigType + " and Platform: " + platform, URAExceptionType.InvalidTunnelConfig);
        }
    }
}

// create single, global instance of the TunnelConfigFactory
var tunnelConfigFactory = new TunnelConfigFactory("tunnelConfigFactory");


/**********************************************************************
   $Author: dbabbitt $
   $Date: 2007/06/12 23:40:40 $
   $Revision: 1.18 $


   Copyright 2001 - 2007. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/
/// <summary>
/// Implementation class for the HttpActiveXTunnelConfig
/// </summary>
function HttpActiveXTunnelConfig (id){
/// region : inheritance --------------------------------------------
    this.base = TunnelConfig;
    this.base(id);
    log.info("[" + id + "]:  HttpActiveXTunnelConfig object created.");

/// region : private fields -----------------------------------------
    this._ctlSuffix = "_ax"; // the suffix applied to the HTML element Id
    this._protocol = "http://"; // the protocol scheme for this implementation

/// region : Properties ---------------------------------------------
 
/// region : Methods ------------------------------------------------

    /// <summary>
    /// Method renders the TunnelConfig's HTML to the target element's child nodes.  The method 
    /// of render varies for each implementation.
    /// </summary>
    this.renderHtml = _renderHtml;
    function _renderHtml() {
        var ctlid = this.Id + this._ctlSuffix;
        return '<object id="' + ctlid + '" ' +
            'classid="CLSID:380BBEC2-4CAE-4ECE-8AFF-36CDE7916386" ' +
            'codebase="' + appPath + '/URA/lib/srdp.cab#Version=5,0,0,0"></object>';
    }

    /// <summary>
    /// Method tells the TunnelConfig to attempt to start the remote session. Raises 
    /// an OnConnect event.
    /// </summary>
    this.connect = _connect;
    function _connect(){
        try{
            // get the ref to the HTML element
            if(this._control == null){
                this._control = this.Element.getElementById(this.Id + this._ctlSuffix);
                if(this._control == null){
                    log.error("[" + this.Id + "]:  HttpActiveXTunnelConfig unable to find rendered object tag in document.");
                    throw this._newError("Unable to target control HTML tag");
                }
            }
            log.debug("[" + this.Id + "]:  HttpActiveXTunnelConfig._control = " + this._control);
            if(typeof(this._control.NewConnection) != "undefined"){
                log.info("[" + this.Id + "]:  HttpActiveXTunnelConfig attempting to connect to host: " + this.HostAddress + ":" + this.HostPort + 
                    " via gateway: " + this.GatewayAddress);
                this._connectCount = 0;
                
                // create the connection object using the destination address
                if(this.HostAddress != ""){
                    if(this.HostPort != ""){
                        this._hostURL = this.HostProtocol + "://" + this.HostAddress + ":" + this.HostPort;
                    } else {
                        this._hostURL = this.HostProtocol + "://" + this.HostAddress;
                    }
                    log.info("[" + this.Id + "]:  HttpActiveXTunnelConfig establishing connection to host: " + this._hostURL);
                    this._connection = this._control.NewConnection(this._hostURL);
                } else {
                    log.error("[" + this.Id + "]:  HttpActiveXTunnelConfig.HostAddress property is invalid and cannot be connected.");
                    throw this._newError("HostAddress property is invalid.");
                }
                
                // set the GatewayBaseUrl on the control
                // note: port override is not allowed
                if(this.GatewayAddress != ""){
                    this._gatewayURL = this._protocol + this.GatewayAddress + this._gatewayName;
                    log.info("[" + this.Id + "]:  HttpActiveXTunnelConfig establishing connection to gateway: " + this._gatewayURL);
                    this._connection.GetPropertyBag().SetProperty("HttpVirtualConnection.GatewayBaseUrl", this._gatewayURL);
                } else {
                    log.error("[" + this.Id + "]:  HttpActiveXTunnelConfig.GatewayAddress address is invalid and cannot be connected.");
                    throw this._newError("GatewayAddress address is invalid.");
                }

                // set the connection classname
                this._connection.GetPropertyBag().SetProperty("ProxyConnection.connectionClasses", "HttpVirtualConnection");
                
                // set the upstream handler class
                if(this.UpsteamHandler != ""){
                    this._connection.GetPropertyBag().SetProperty("HttpVirtualConnection.upstreamClasses", this.UpstreamHandler);
                }
                
                if(this.DownstreamHandler != ""){
                    this._connection.GetPropertyBag().SetProperty("HttpVirtualConnection.downstreamClasses", this.DownstreamHandler);
                }

                // set the logging for the control
                this._control.EnableFileLogging("c:\\temp\\Surgient_HttpActiveXTunnelConfig.log");

                // now try to start the connection
                this._connection.Start();
                
                // finally set up a callback to verify the connection was made
                this._setTimeout(this.Id + "._verifyConnection()", 1000);

            } else {
                // if the control has tried to connect 5 times, it's not going to be 
                // successful so message that up to a handler
                if(this._connectCount < 25){
                    // the ActiveX control is not yet ready, so re-call this function after 
                    // a set timeout
                    this._setTimeout(this.Id + ".connect()", 1000);
                    this._connectCount++;
                } else {
                    log.fatal("[" + this.Id + "]:  HTTPActiveXTunnelConfig control unable to initialize due to a download or installation error.");
                    // raise an OnLoadError event
                    this._raiseEvent("OnLoadError", null);
                }
            }
        } catch(e){
            log.fatal("[" + this.Id + "]:  HttpActiveXTunnelConfig suffered a fatal error during the connect() method: " + e.message);
            this.connectError(e);
            return;
        }
    }

    /// <summary>
    /// Private method to verify the TunnelConfig's connection before raising the OnConnect event.
    /// </summary>    
    this._verifyConnection = _verifyConnection;
    function _verifyConnection(){
        try
        {
            if(this._connection == null){
                log.error("[" + this.Id + "]:  HttpActiveXTunnelConfig control's Connection object was uninstantiated.");
                throw this._newError("Connection was uninstantiated in ActiveX control.");
            }
            if(this.isConnected()){
                //this._setTimeout(this.Id + "._pollConnection()", 1000);
                log.info("[" + this.Id + "]:  HttpActiveXTunnelConfig successfully connected to host: " + this._hostURL + " via gateway: " + this._gatewayURL);
                this._raiseEvent("OnConnect", null);
            } else {
                if(this._verifyCount < 20){
                    this._verifyCount++;
                    this._setTimeout(this.Id + "._verifyConnection()", 1000);
                } else {
                    log.error("[" + this.Id + "]:  HttpActiveXTunnelConfig was unable to verify to host: " + this._hostURL + " via gateway: " + this._gatewayURL);
                    throw this._newError("HttpActiveXTunnelConfig connection verification failed.");
                }
            }
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  HttpActiveXTunnelConfig suffered a fatal error attempting to verify the connection: " + e.message);
            this.connectError(e);
            return;
        }
    }

    /// <summary>
    /// Private method that polls the control every second to determine if the 
    /// connection is still viable.  If not, it raises the OnDisconnect event.
    /// </summary>
    this._pollConnection = _pollConnection;
    function _pollConnection(){
        if(this.isConnected()){
            this._setTimeout(this.Id + "._pollConnection()", 1000);
        } else {
            log.info("[" + this.Id + "]:  HttpActiveXTunnelConfig connection poll returned a disconnected state.");
            this._raiseEvent("OnDisconnect", null);
        }
    }

    /// <summary>
    /// Method tells the TunnelConfig to attempt to disconnect.
    /// </summary>
    this.disconnect = _disconnect;
    function _disconnect(args) {
        // calls the Abort() method on the connection object
        this._connection.Stop();
        log.info("[" + this.Id + "]:  HttpActiveXTunnelConfig successfully disconnected from host: " + this._hostURL + " via gateway: " + this._gatewayURL);
        // raise the OnDisconnect event, passing the results up the chain
        this._raiseEvent("OnDisconnect", args);
    }

    /// <summary>
    /// Method called by the TunnelConfig instance when a connection error has occurred.  Raises 
    /// an OnConnectError event.
    /// </summary>
    this.connectError = _connectError;
    function _connectError(error) {
        log.error("[" + this.Id + "]:  HttpActiveXTunnelConfig failed to connect to host: " + this._hostURL + " via gateway: " + this._gatewayURL);
        // raise the OnConnectError event
        this._raiseEvent("OnConnectError", error.message);
    }

    /// <summary>
    /// Gets the local IPAddress of the TunnelConfig.
    /// </summary>
    /// <return type="string">the local IPAddress of the TunnelConfig</return>
    this.getDestinationIPAddress = _getDestinationIPAddress;
    function _getDestinationIPAddress() {
        try
        {
        	return this._connection.GetLocalIPString();
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  HttpActiveXTunnelConfig.getDestinationIPAddress() suffered a fatal error: " + e.message);
            throw this._newError("HttpActiveXTunnelConfig connection does not return address: " + e.message);
        }
    }

    /// <summary>
    /// Gets the local Port of the TunnelConfig.
    /// </summary>
    this.getDestinationPort = _getDestinationPort;
    function _getDestinationPort() {
        try
        {
        	return this._connection.GetLocalPort();
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  HttpActiveXTunnelConfig.getDestinationPort() suffered a fatal error: " + e.message);
            throw this._newError("HttpActiveXTunnelConfig connection does not return port: " + e.message);
        }
    }

    /// <summary>
    /// Method determines if the control is actually connected or not, helpful for polling 
    /// exercises and error checking in the URACoordinators.
    /// </summary>
    this.isConnected = _isConnected;
    function _isConnected(){
        try
        {
            if(this._connection.IsStartedOk()){
                log.info("[" + this.Id + "]:  HttpActiveXTunnelConfig.isConnected returned: true");
                return true;
            } else {
                log.info("[" + this.Id + "]:  HttpActiveXTunnelConfig.isConnected returned: false");
                return false;
            }
        }
        catch (e)
        {
            log.info("[" + this.Id + "]:  HttpActiveXTunnelConfig.isConnected caught the following exception: " + e.message);
            throw this._newError("HttpActiveXTunnelConfig.isConnected raised exception.");
        }
    }

    /// <summary>
    /// Method gets the ActiveX or Applet control of the TermClient depending upon what 
    /// ControlPlatform has been deployed.
    /// </summary>
    /// <return type="object">the internal control, if this control has not been properly
    /// initialized this method ***can return null***</return>
    this.getControl = _getControl;
    function _getControl(){
        return this._control;
    }
}

// register this instance with the TunnelConfigFactory
tunnelConfigFactory.registerTunnelConfig(ControlPlatform.ActiveX, TunnelConfigType.HTTPTunnel, "HttpActiveXTunnelConfig");


/**********************************************************************
   $Author: dbabbitt $
   $Date: 2007/06/12 23:40:40 $
   $Revision: 1.19 $


   Copyright 2001 - 2007. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/
/// <summary>
/// Implementation class for the HttpsActiveXTunnelConfig
/// </summary>
function HttpsActiveXTunnelConfig (id){
/// region : inheritance --------------------------------------------
    this.base = TunnelConfig;
    this.base(id);
    log.info("[" + id + "]:  HttpsActiveXTunnelConfig object created.");

/// region : private fields -----------------------------------------
    this._ctlSuffix = "_ax"; // the suffix applied to the HTML element Id
    this._protocol = "https://"; // the protocol scheme for this implementation

/// region : Properties ---------------------------------------------
 
/// region : Methods ------------------------------------------------

    /// <summary>
    /// Method renders the TunnelConfig's HTML to the target element's child nodes.  The method 
    /// of render varies for each implementation.
    /// </summary>
    this.renderHtml = _renderHtml;
    function _renderHtml() {
        var ctlid = this.Id + this._ctlSuffix;
        return '<object id="' + ctlid + '" ' +
            'classid="CLSID:380BBEC2-4CAE-4ECE-8AFF-36CDE7916386" ' +
            'codebase="' + appPath + '/URA/lib/srdp.cab#Version=5,0,0,0"></object>';
    }

    /// <summary>
    /// Method tells the TunnelConfig to attempt to start the remote session. Raises 
    /// an OnConnect event.
    /// </summary>
    this.connect = _connect;
    function _connect(){
        try{
            // get the ref to the HTML element
            if(this._control == null){
                this._control = this.Element.getElementById(this.Id + this._ctlSuffix);
                if(this._control == null){
                    log.error("[" + this.Id + "]:  HttpsActiveXTunnelConfig unable to find rendered object tag in document.");
                    throw this._newError("Unable to target control HTML tag");
                }
            }
            log.debug("[" + this.Id + "]:  HttpsActiveXTunnelConfig._control = " + this._control);
            if(typeof(this._control.NewConnection) != "undefined"){
                log.info("[" + this.Id + "]:  HttpsActiveXTunnelConfig attempting to connect to host: " + this.HostAddress + ":" + this.HostPort + 
                    " via gateway: " + this.GatewayAddress);
                this._connectCount = 0;
                
                // create the connection object using the destination address
                if(this.HostAddress != ""){
                    if(this.HostPort != ""){
                        this._hostURL = this.HostProtocol + "://" + this.HostAddress + ":" + this.HostPort;
                    } else {
                        this._hostURL = this.HostProtocol + "://" + this.HostAddress;
                    }
                    log.info("[" + this.Id + "]:  HttpsActiveXTunnelConfig establishing connection to host: " + this._hostURL);
                    this._connection = this._control.NewConnection(this._hostURL);
                } else {
                    log.error("[" + this.Id + "]:  HttpsActiveXTunnelConfig.HostAddress property is invalid and cannot be connected.");
                    throw this._newError("HostAddress property is invalid.");
                }
                
                // set the GatewayBaseUrl on the control
                // Note: port override is not allowed
                if(this.GatewayAddress != ""){
                    this._gatewayURL = this._protocol + this.GatewayAddress + this._gatewayName;
                    log.info("[" + this.Id + "]:  HttpsActiveXTunnelConfig establishing connection to gateway: " + this._gatewayURL);
                    this._connection.GetPropertyBag().SetProperty("HttpVirtualConnection.GatewayBaseUrl", this._gatewayURL);
                } else {
                    log.error("[" + this.Id + "]:  HttpsActiveXTunnelConfig.GatewayAddress address is invalid and cannot be connected.");
                    throw this._newError("GatewayAddress address is invalid.");
                }

                // set the connection classname
                this._connection.GetPropertyBag().SetProperty("ProxyConnection.connectionClasses", "HttpVirtualConnection");
                
                // set the upstream handler class
                if(this.UpsteamHandler != ""){
                    this._connection.GetPropertyBag().SetProperty("HttpVirtualConnection.upstreamClasses", this.UpstreamHandler);
                }
                
                if(this.DownstreamHandler != ""){
                    this._connection.GetPropertyBag().SetProperty("HttpVirtualConnection.downstreamClasses", this.DownstreamHandler);
                }

                // set the logging for the control
                this._control.EnableFileLogging("c:\\temp\\Surgient_HttpsActiveXTunnelConfig.log");

                // now try to start the connection
                this._connection.Start();
                
                // finally set up a callback to verify the connection was made
                this._setTimeout(this.Id + "._verifyConnection()", 1000);

            } else {
                // if the control has tried to connect 5 times, it's not going to be 
                // successful so message that up to a handler
                if(this._connectCount < 25){
                    // the ActiveX control is not yet ready, so re-call this function after 
                    // a set timeout
                    this._setTimeout(this.Id + ".connect()", 1000);
                    this._connectCount++;
                } else {
                    log.fatal("[" + this.Id + "]:  HttpsActiveXTunnelConfig control unable to initialize due to a download or installation error.");
                    // raise an OnLoadError event
                    this._raiseEvent("OnLoadError", null);
                }
            }
        } catch(e){
            log.fatal("[" + this.Id + "]:  HttpsActiveXTunnelConfig suffered a fatal error during the connect() method: " + e.message);
            this.connectError(e);
            return;
        }
    }

    /// <summary>
    /// Private method to verify the TunnelConfig's connection before raising the OnConnect event.
    /// </summary>    
    this._verifyConnection = _verifyConnection;
    function _verifyConnection(){
        try
        {
            if(this._connection == null){
                log.error("[" + this.Id + "]:  HttpsActiveXTunnelConfig control's Connection object was uninstantiated.");
                throw this._newError("Connection was uninstantiated in ActiveX control.");
            }
            if(this.isConnected()){
                //this._setTimeout(this.Id + "._pollConnection()", 1000);
                log.info("[" + this.Id + "]:  HttpsActiveXTunnelConfig successfully connected to host: " + this._hostURL + " via gateway: " + this._gatewayURL);
                this._raiseEvent("OnConnect", null);
            } else {
                if(this._verifyCount < 20){
                    this._verifyCount++;
                    this._setTimeout(this.Id + "._verifyConnection()", 1000);
                } else {
                    log.error("[" + this.Id + "]:  HttpsActiveXTunnelConfig was unable to verify to host: " + this._hostURL + " via gateway: " + this._gatewayURL);
                    throw this._newError("HttpsActiveXTunnelConfig connection verification failed.");
                }
            }
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  HttpsActiveXTunnelConfig suffered a fatal error attempting to verify the connection: " + e.message);
            this.connectError(e);
            return;
        }
    }

    /// <summary>
    /// Private method that polls the control every second to determine if the 
    /// connection is still viable.  If not, it raises the OnDisconnect event.
    /// </summary>
    this._pollConnection = _pollConnection;
    function _pollConnection(){
        if(this.isConnected()){
            this._setTimeout(this.Id + "._pollConnection()", 1000);
        } else {
            log.info("[" + this.Id + "]:  HttpsActiveXTunnelConfig connection poll returned a disconnected state.");
            this._raiseEvent("OnDisconnect", null);
        }
    }

    /// <summary>
    /// Method tells the TunnelConfig to attempt to disconnect.
    /// </summary>
    this.disconnect = _disconnect;
    function _disconnect(args) {
        // calls the Abort() method on the connection object
        this._connection.Stop();
        log.info("[" + this.Id + "]:  HttpsActiveXTunnelConfig successfully disconnected from host: " + this._hostURL + " via gateway: " + this._gatewayURL);
        // raise the OnDisconnect event, passing the results up the chain
        this._raiseEvent("OnDisconnect", args);
    }

    /// <summary>
    /// Method called by the TunnelConfig instance when a connection error has occurred.  Raises 
    /// an OnConnectError event.
    /// </summary>
    this.connectError = _connectError;
    function _connectError(error) {
        log.error("[" + this.Id + "]:  HttpsActiveXTunnelConfig failed to connect to host: " + this._hostURL + " via gateway: " + this._gatewayURL);
        // raise the OnConnectError event
        this._raiseEvent("OnConnectError", error.message);
    }

    /// <summary>
    /// Gets the local IPAddress of the TunnelConfig.
    /// </summary>
    /// <return type="string">the local IPAddress of the TunnelConfig</return>
    this.getDestinationIPAddress = _getDestinationIPAddress;
    function _getDestinationIPAddress() {
        try
        {
        	return this._connection.GetLocalIPString();
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  HttpsActiveXTunnelConfig.getDestinationIPAddress() suffered a fatal error: " + e.message);
            throw this._newError("HttpsActiveXTunnelConfig connection does not return address: " + e.message);
        }
    }

    /// <summary>
    /// Gets the local Port of the TunnelConfig.
    /// </summary>
    this.getDestinationPort = _getDestinationPort;
    function _getDestinationPort() {
        try
        {
        	return this._connection.GetLocalPort();
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  HttpsActiveXTunnelConfig.getDestinationPort() suffered a fatal error: " + e.message);
            throw this._newError("HttpsActiveXTunnelConfig connection does not return port: " + e.message);
        }
    }

    /// <summary>
    /// Method determines if the control is actually connected or not, helpful for polling 
    /// exercises and error checking in the URACoordinators.
    /// </summary>
    this.isConnected = _isConnected;
    function _isConnected(){
        try
        {
            if(this._connection.IsStartedOk()){
            log.info("[" + this.Id + "]:  HttpsActiveXTunnelConfig.isConnected returned: true");
                return true;
            } else {
                log.info("[" + this.Id + "]:  HttpsActiveXTunnelConfig.isConnected returned: false");
                return false;
            }
        }
        catch (e)
        {
            log.info("[" + this.Id + "]:  HttpsActiveXTunnelConfig.isConnected caught the following exception: " + e.message);
            throw this._newError("HttpsActiveXTunnelConfig.isConnected raised exception.");
        }
    }

    /// <summary>
    /// Method gets the ActiveX or Applet control of the TermClient depending upon what 
    /// ControlPlatform has been deployed.
    /// </summary>
    /// <return type="object">the internal control, if this control has not been properly
    /// initialized this method ***can return null***</return>
    this.getControl = _getControl;
    function _getControl(){
        return this._control;
    }
}

// register this instance with the TunnelConfigFactory
tunnelConfigFactory.registerTunnelConfig(ControlPlatform.ActiveX, TunnelConfigType.HTTPSTunnel, "HttpsActiveXTunnelConfig");


/**********************************************************************
   $Author: greynold $
   $Date: 2006/04/17 20:23:59 $
   $Revision: 1.8 $


   Copyright 2001 - 2004. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/
/// <summary>
/// Implementation class for the NoOpActiveXTunnelConfig
/// </summary>
function NoOpActiveXTunnelConfig (id){
/// region : inheritance --------------------------------------------
    this.base = TunnelConfig;
    this.base(id);
    log.info("[" + this.Id + "]:  NoOpActiveXTunnelConfig object created.");

/// region : private fields -----------------------------------------
    this._ctlSuffix = ""; // the suffix applied to the HTML element Id
    this._protocol = ""; // the protocol scheme for this implementation

/// region : Properties ---------------------------------------------
 
/// region : Methods ------------------------------------------------

    /// <summary>
    /// Method renders the TunnelConfig's HTML to the target element's child nodes.  The method 
    /// of render varies for each implementation.
    /// </summary>
    this.renderHtml = _renderHtml;
    function _renderHtml() {
        return '';
    }

    /// <summary>
    /// Method tells the TunnelConfig to attempt to start the remote session. Raises 
    /// an OnConnect event.
    /// </summary>
    this.connect = _connect;
    function _connect(){
        if(this.HostAddress != ""){
            if(this.HostPort != ""){
                this._hostURL = this.HostProtocol + "://" + this.HostAddress + ":" + this.HostPort;
            } else {
                this._hostURL = this.HostProtocol + "://" + this.HostAddress;
            }
            log.info("[" + this.Id + "]:  NoOpActiveXTunnelConfig establishing connection to host: " + this._hostURL);
        } else {
            log.error("[" + this.Id + "]:  NoOpActiveXTunnelConfig.HostAddress property is invalid and cannot be connected.");
            throw this._newError("HostAddress property is invalid.");
        }
        // set up a callback to verify the connection was made, this releases the browser
        // from the thread and allows it to process the document writes done by the URACoordinator
        this._setTimeout(this.Id + "._verifyConnection()", 1000);
    }

    /// <summary>
    /// Private method to verify the TunnelConfig's connection before raising the OnConnect event.
    /// </summary>    
    this._verifyConnection = _verifyConnection;
    function _verifyConnection(){
        log.info("[" + this.Id + "]:  NoOpActiveXTunnelConfig successfully connected to host: " + this._hostURL + " via direct connection.");
        this._raiseEvent("OnConnect", null);
    }

    /// <summary>
    /// Private method that polls the control every second to determine if the 
    /// connection is still viable.  If not, it raises the OnDisconnect event.
    /// </summary>
    this._pollConnection = _pollConnection;
    function _pollConnection(){
        return;
    }

    /// <summary>
    /// Method tells the TunnelConfig to attempt to disconnect.
    /// </summary>
    this.disconnect = _disconnect;
    function _disconnect(args) {
        log.info("[" + this.Id + "]:  NoOpActiveXTunnelConfig successfully disconnected from host: " + this._hostURL + " via direct connection.");
        this._raiseEvent("OnDisconnect", args);
    }

    /// <summary>
    /// Method called by the TunnelConfig instance when a connection error has occurred.  Raises 
    /// an OnConnectError event.
    /// </summary>
    this.connectError = _connectError;
    function _connectError(error) {
        log.error("[" + this.Id + "]:  NoOpActiveXTunnelConfig failed to connect to host: " + this._hostURL + 
            "via direct connection with the following error: " + error);
        this._raiseEvent("OnConnectError", error);
    }

    /// <summary>
    /// Gets the local IPAddress of the TunnelConfig.
    /// </summary>
    /// <return type="string">the local IPAddress of the TunnelConfig</return>
    this.getDestinationIPAddress = _getDestinationIPAddress;
    function _getDestinationIPAddress() {
        return this.HostAddress;
    }

    /// <summary>
    /// Gets the local Port of the TunnelConfig.
    /// </summary>
    this.getDestinationPort = _getDestinationPort;
    function _getDestinationPort() {
        return this.HostPort;
    }

    /// <summary>
    /// Method determines if the control is actually connected or not, helpful for polling 
    /// exercises and error checking in the URACoordinators.
    /// </summary>
    this.isConnected = _isConnected;
    function _isConnected(){
        log.info("[" + this.Id + "]:  NoOpActiveXTunnelConfig.isConnected returned: true");
        return true;
    }

    /// <summary>
    /// Method gets the ActiveX or Applet control of the TermClient depending upon what 
    /// ControlPlatform has been deployed.
    /// </summary>
    /// <return type="object">the internal control, if this control has not been properly
    /// initialized this method ***can return null***</return>
    this.getControl = _getControl;
    function _getControl(){
        return new Object();
    }
}

// register this instance with the TunnelConfigFactory
tunnelConfigFactory.registerTunnelConfig(ControlPlatform.ActiveX, TunnelConfigType.NoOpTunnel, "NoOpActiveXTunnelConfig");


/**********************************************************************
   $Author: dbabbitt $
   $Date: 2007/06/12 23:40:40 $
   $Revision: 1.4 $


   Copyright 2001 - 2007. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/
/// <summary>
/// Implementation class for the SocketProxyActiveXTunnelConfig
/// </summary>
function SocketProxyActiveXTunnelConfig (id){
/// region : inheritance --------------------------------------------
    this.base = TunnelConfig;
    this.base(id);
    log.info("[" + id + "]:  SocketProxyActiveXTunnelConfig object created.");

/// region : private fields -----------------------------------------
    this._ctlSuffix = "_ax"; // the suffix applied to the HTML element Id
    this._protocol = "tcp://"; // the protocol scheme for this implementation

/// region : Properties ---------------------------------------------
 
/// region : Methods ------------------------------------------------

    /// <summary>
    /// Method renders the TunnelConfig's HTML to the target element's child nodes.  The method 
    /// of render varies for each implementation.
    /// </summary>
    this.renderHtml = _renderHtml;
    function _renderHtml() {
        var ctlid = this.Id + this._ctlSuffix;
        return '<object id="' + ctlid + '" ' +
            'classid="CLSID:380BBEC2-4CAE-4ECE-8AFF-36CDE7916386" ' +
            'codebase="' + appPath + '/URA/lib/srdp.cab#Version=5,3,0,0"></object>';
    }

    /// <summary>
    /// Method tells the TunnelConfig to attempt to start the remote session. Raises 
    /// an OnConnect event.
    /// </summary>
    this.connect = _connect;
    function _connect(){
        try{
            // get the ref to the HTML element
            if(this._control == null){
                this._control = this.Element.getElementById(this.Id + this._ctlSuffix);
                if(this._control == null){
                    log.error("[" + this.Id + "]:  SocketProxyActiveXTunnelConfig unable to find rendered object tag in document.");
                    throw this._newError("Unable to target control HTML tag");
                }
            }
            log.debug("[" + this.Id + "]:  SocketProxyActiveXTunnelConfig._control = " + this._control);
            if(typeof(this._control.NewConnection) != "undefined"){
                log.info("[" + this.Id + "]:  SocketProxyActiveXTunnelConfig attempting to connect to host: " + this.HostAddress + ":" + this.HostPort + 
                    " via gateway: " + this.GatewayAddress + ":" + this.GatewayPort);
                this._connectCount = 0;
                
                // create the connection object using the destination address
                if(this.HostAddress != ""){
                    if(this.HostPort != ""){
                        this._hostURL = this.HostProtocol + "://" + this.HostAddress + ":" + this.HostPort;
                    } else {
                        this._hostURL = this.HostProtocol + "://" + this.HostAddress;
                    }
                    log.info("[" + this.Id + "]:  SocketProxyActiveXTunnelConfig establishing connection to host: " + this._hostURL);
                    this._connection = this._control.NewConnection(this._hostURL);
                } else {
                    log.error("[" + this.Id + "]:  SocketProxyActiveXTunnelConfig.HostAddress property is invalid and cannot be connected.");
                    throw this._newError("HostAddress property is invalid.");
                }
                
                // set the Gateway IP address (and port, optionally)
                if(this.GatewayAddress != ""){
                    if(this.GatewayPort != ""){
                        this._gatewayURL = this._protocol + this.GatewayAddress + ":" + this.GatewayPort;
                    } else {
                        this._gatewayURL = this._protocol + this.GatewayAddress;
                    }
                    log.info("[" + this.Id + "]:  SocketProxyActiveXTunnelConfig establishing connection to gateway: " + this._gatewayURL);
                    this._connection.GetPropertyBag().SetProperty("SocketProxyConnection.Gateway", this.GatewayAddress);
                    if(this.GatewayPort != ""){
                        this._connection.GetPropertyBag().SetProperty("SocketProxyConnection.GatewayPort", this.GatewayPort);
                    }
                } else {
                    log.error("[" + this.Id + "]:  SocketProxyActiveXTunnelConfig.GatewayAddress address is invalid and cannot be connected.");
                    throw this._newError("GatewayAddress address is invalid.");
                }

                // set the connection classname
                this._connection.GetPropertyBag().SetProperty("ProxyConnection.connectionClasses", "SocketProxyConnection");
                
                // set the logging for the control
                this._control.EnableFileLogging("c:\\temp\\Surgient_SocketProxyActiveXTunnelConfig.log");

                // now try to start the connection
                this._connection.Start();
                
                // finally set up a callback to verify the connection was made
                this._setTimeout(this.Id + "._verifyConnection()", 1000);

            } else {
                // if the control has tried to connect 5 times, it's not going to be 
                // successful so message that up to a handler
                if(this._connectCount < 25){
                    // the ActiveX control is not yet ready, so re-call this function after 
                    // a set timeout
                    this._setTimeout(this.Id + ".connect()", 1000);
                    this._connectCount++;
                } else {
                    log.fatal("[" + this.Id + "]:  SocketProxyActiveXTunnelConfig control unable to initialize due to a download or installation error.");
                    // raise an OnLoadError event
                    this._raiseEvent("OnLoadError", null);
                }
            }
        } catch(e){
            log.fatal("[" + this.Id + "]:  SocketProxyActiveXTunnelConfig suffered a fatal error during the connect() method: " + e.message);
            this.connectError(e);
            return;
        }
    }

    /// <summary>
    /// Private method to verify the TunnelConfig's connection before raising the OnConnect event.
    /// </summary>    
    this._verifyConnection = _verifyConnection;
    function _verifyConnection(){
        try
        {
            if(this._connection == null){
                log.error("[" + this.Id + "]:  SocketProxyActiveXTunnelConfig control's Connection object was uninstantiated.");
                throw this._newError("Connection was uninstantiated in ActiveX control.");
            }
            if(this.isConnected()){
                //this._setTimeout(this.Id + "._pollConnection()", 1000);
                log.info("[" + this.Id + "]:  SocketProxyActiveXTunnelConfig successfully connected to host: " + this._hostURL + " via gateway: " + this._gatewayURL);
                this._raiseEvent("OnConnect", null);
            } else {
                if(this._verifyCount < 20){
                    this._verifyCount++;
                    this._setTimeout(this.Id + "._verifyConnection()", 1000);
                } else {
                    log.error("[" + this.Id + "]:  SocketProxyActiveXTunnelConfig was unable to verify to host: " + this._hostURL + " via gateway: " + this._gatewayURL);
                    throw this._newError("SocketProxyActiveXTunnelConfig connection verification failed.");
                }
            }
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  SocketProxyActiveXTunnelConfig suffered a fatal error attempting to verify the connection: " + e.message);
            this.connectError(e);
            return;
        }
    }

    /// <summary>
    /// Private method that polls the control every second to determine if the 
    /// connection is still viable.  If not, it raises the OnDisconnect event.
    /// </summary>
    this._pollConnection = _pollConnection;
    function _pollConnection(){
        if(this.isConnected()){
            this._setTimeout(this.Id + "._pollConnection()", 1000);
        } else {
            log.info("[" + this.Id + "]:  SocketProxyActiveXTunnelConfig connection poll returned a disconnected state.");
            this._raiseEvent("OnDisconnect", null);
        }
    }

    /// <summary>
    /// Method tells the TunnelConfig to attempt to disconnect.
    /// </summary>
    this.disconnect = _disconnect;
    function _disconnect(args) {
        // calls the Abort() method on the connection object
        this._connection.Stop();
        log.info("[" + this.Id + "]:  SocketProxyActiveXTunnelConfig successfully disconnected from host: " + this._hostURL + " via gateway: " + this._gatewayURL);
        // raise the OnDisconnect event, passing the results up the chain
        this._raiseEvent("OnDisconnect", args);
    }

    /// <summary>
    /// Method called by the TunnelConfig instance when a connection error has occurred.  Raises 
    /// an OnConnectError event.
    /// </summary>
    this.connectError = _connectError;
    function _connectError(error) {
        log.error("[" + this.Id + "]:  SocketProxyActiveXTunnelConfig failed to connect to host: " + this._hostURL + " via gateway: " + this._gatewayURL);
        // raise the OnConnectError event
        this._raiseEvent("OnConnectError", error.message);
    }

    /// <summary>
    /// Gets the local IPAddress of the TunnelConfig.
    /// </summary>
    /// <return type="string">the local IPAddress of the TunnelConfig</return>
    this.getDestinationIPAddress = _getDestinationIPAddress;
    function _getDestinationIPAddress() {
        try
        {
        	return this._connection.GetLocalIPString();
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  SocketProxyActiveXTunnelConfig.getDestinationIPAddress() suffered a fatal error: " + e.message);
            throw this._newError("SocketProxyActiveXTunnelConfig connection does not return address: " + e.message);
        }
    }

    /// <summary>
    /// Gets the local Port of the TunnelConfig.
    /// </summary>
    this.getDestinationPort = _getDestinationPort;
    function _getDestinationPort() {
        try
        {
        	return this._connection.GetLocalPort();
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  SocketProxyActiveXTunnelConfig.getDestinationPort() suffered a fatal error: " + e.message);
            throw this._newError("SocketProxyActiveXTunnelConfig connection does not return port: " + e.message);
        }
    }

    /// <summary>
    /// Method determines if the control is actually connected or not, helpful for polling 
    /// exercises and error checking in the URACoordinators.
    /// </summary>
    this.isConnected = _isConnected;
    function _isConnected(){
        try
        {
            if(this._connection.IsStartedOk()){
                log.info("[" + this.Id + "]:  SocketProxyActiveXTunnelConfig.isConnected returned: true");
                return true;
            } else {
                log.info("[" + this.Id + "]:  SocketProxyActiveXTunnelConfig.isConnected returned: false");
                return false;
            }
        }
        catch (e)
        {
            log.info("[" + this.Id + "]:  SocketProxyActiveXTunnelConfig.isConnected caught the following exception: " + e.message);
            throw this._newError("SocketProxyActiveXTunnelConfig.isConnected raised exception.");
        }
    }

    /// <summary>
    /// Method gets the ActiveX or Applet control of the TermClient depending upon what 
    /// ControlPlatform has been deployed.
    /// </summary>
    /// <return type="object">the internal control, if this control has not been properly
    /// initialized this method ***can return null***</return>
    this.getControl = _getControl;
    function _getControl(){
        return this._control;
    }
}

// register this instance with the TunnelConfigFactory
tunnelConfigFactory.registerTunnelConfig(ControlPlatform.ActiveX, TunnelConfigType.SocketProxy, "SocketProxyActiveXTunnelConfig");


/**********************************************************************
   $Author: dbabbitt $
   $Date: 2007/06/12 15:57:58 $
   $Revision: 1.19 $


   Copyright 2001 - 2007. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/
/// <summary>
/// Implementation class for the HttpJavaTunnelConfig
/// </summary>
function HttpJavaTunnelConfig (id){
/// region : inheritance --------------------------------------------
    this.base = TunnelConfig;
    this.base(id);
    log.info("[" + id + "]:  HttpJavaTunnelConfig object created.");

/// region : private fields -----------------------------------------
    this._ctlSuffix = "_ax"; // the suffix applied to the HTML element Id
    this._protocol = "http://"; // the protocol scheme for this implementation

/// region : Properties ---------------------------------------------
    /// <summary>
    /// Gets/sets the name of the class that handles the upstream encoding.  This must be one of the following
    /// values:  "" or a comma delimited list of:  "OctetStreamUpHandler", "MultipartFormUpHandler" , "Base64UpHandler"
    /// </summary>   
    this.UpstreamHandler = "com.surgient.localproxy.connections.http.OctetStreamHandler$UpHandler,com.surgient.localproxy.connections.http.MultipartFormUpHandler,com.surgient.localproxy.connections.http.Base64Handler$UpHandler";
    
    /// <summary>
    /// Gets/sets the name of the class that handles the downstream encoding.  This must be one of the following
    /// values:  "" or a comma delimited list of:  "OctetStreamDnHandler", "Base64DnHandler"
    /// </summary>  
    this.DownstreamHandler = "com.surgient.localproxy.connections.http.OctetStreamHandler$DnHandler,com.surgient.localproxy.connections.http.Base64Handler$DnHandler";
 
/// region : Methods ------------------------------------------------

    /// <summary>
    /// Method renders the TunnelConfig's HTML to the target element's child nodes.  The method 
    /// of render varies for each implementation.
    /// </summary>
    this.renderHtml = _renderHtml;
    function _renderHtml() {
        var ctlid = this.Id + this._ctlSuffix;
        return '<applet id="' + ctlid + '" code="com.surgient.localproxy.applet.ProxyApplet.class" archive="' + appPath + '/URA/lib/LocalProxyApplet.jar"' + 
        ' height="0" width="0">' + 
        '<param name="logLevel" value="5" />' + 
        '<param name="cabbase" value="' + appPath + '/URA/lib/LocalProxyApplet11.cab" />' + 
        '</applet>';
    }

    /// <summary>
    /// Method tells the TunnelConfig to attempt to start the remote session. Raises 
    /// an OnConnect event.
    /// </summary>
    this.connect = _connect;
    function _connect(){
        try{
            // get the ref to the HTML element
            if(this._control == null){
                this._control = this.Element.getElementById(this.Id + this._ctlSuffix);
                if(this._control == null){
                    log.error("[" + this.Id + "]:  HttpJavaTunnelConfig unable to find rendered object tag in document.");
                    throw this._newError("Unable to target control HTML tag");
                }
            }
            log.debug("[" + this.Id + "]:  HttpJavaTunnelConfig._control = " + this._control.tagName);
            
            try
            {
            	// the isStarted method is a simple boolean test, the results of which don't matter 
                // at this point, to verify that the control has been loaded properly this method just 
                // needs to return a value and not throw an exception because the method is not supported.
                if(this._control.isStarted()){
                    log.info("[" + this.Id + "]:  HttpJavaTunnelConfig attempting to connect to host: " + this.HostAddress + ":" + this.HostPort + 
                        " via gateway: " + this.GatewayAddress);
                    this._connectCount = 0;

                    // create the connection object using the destination address
                    if(this.HostAddress != ""){
                        if(this.HostPort != ""){
                            this._hostURL = this.HostProtocol + "://" + this.HostAddress + ":" + this.HostPort;
                        } else {
                            this._hostURL = this.HostProtocol + "://" + this.HostAddress;
                        }
                        log.info("[" + this.Id + "]:  HttpJavaTunnelConfig establishing connection to host: " + this._hostURL);
                        this._connection = this._control.newConnection(this._hostURL);
                    } else {
                        log.error("[" + this.Id + "]:  HttpJavaTunnelConfig.HostAddress property is invalid and cannot be connected.");
                        throw this._newError("HostAddress property is invalid.");
                    }

                    // set the GatewayBaseUrl on the control
                    // note: port override is not allowed
                    if(this.GatewayAddress != ""){
                        this._gatewayURL = this._protocol + this.GatewayAddress + this._gatewayName;
                        log.info("[" + this.Id + "]:  HttpJavaTunnelConfig establishing connection to gateway: " + this._gatewayURL);
                        this._connection.getPropertyBag().setProperty("HttpVirtualConnection.GatewayBaseUrl", this._gatewayURL);
                    } else {
                        log.error("[" + this.Id + "]:  HttpJavaTunnelConfig.GatewayAddress address is invalid and cannot be connected.");
                        throw this._newError("GatewayAddress address is invalid.");
                    }

                    // set the connection classname
                    this._connection.getPropertyBag().setProperty("ProxyConnection.connectionClasses", "com.surgient.localproxy.connections.http.HttpVirtualConnection");

                    // set the upstream handler class
                    if(this.UpsteamHandler != ""){
                        this._connection.getPropertyBag().setProperty("HttpVirtualConnection.upstreamClasses", this.UpstreamHandler);
                    }

                    if(this.DownstreamHandler != ""){
                        this._connection.getPropertyBag().setProperty("HttpVirtualConnection.downstreamClasses", this.DownstreamHandler);
                    }

                    // now try to start the connection
                    this._connection.asyncStart();

                    // finally set up a callback to verify the connection was made
                    this._setTimeout(this.Id + "._verifyConnection()", 1000);                    
                } else {
                    log.error("[" + this.Id + "]: LocalProxy applet does not show isStarted method.");
                    throw this._newError("No isStarted method");
                }
            }
            catch (ex)
            {
                log.debug("[" + this.Id + "]:  HttpJavaTunnelConfig control error while trying to start: " + ex.message);
                // on numerous failures to start connecting, raise OnLoadError
                if(this._connectCount < 25){
                    // the applet is not yet ready, so re-call this function after a set timeout
                    this._setTimeout(this.Id + ".connect()", 1000);
                    this._connectCount++;
                } else {
                    log.fatal("[" + this.Id + "]:  HttpJavaTunnelConfig control unable to initialize due to a download or installation error.");
                    // raise an OnLoadError event
                    this._raiseEvent("OnLoadError", null);
                }
            }
        } catch(e){
            log.fatal("[" + this.Id + "]:  HttpJavaTunnelConfig suffered a fatal error during the connect() method: " + e.message);
            this.connectError(e);
            return;
        }
    }

    /// <summary>
    /// Private method to verify the TunnelConfig's connection before raising the OnConnect event.
    /// </summary>    
    this._verifyConnection = _verifyConnection;
    function _verifyConnection(){
        try
        {
            if(this._connection == null){
                log.error("[" + this.Id + "]:  HttpJavaTunnelConfig control's Connection object was uninstantiated.");
                throw this._newError("Connection was uninstantiated in Applet control.");
            }
            if(this._checkConnected()){
                log.info("[" + this.Id + "]:  HttpJavaTunnelConfig successfully connected to host: " + this._hostURL + " via gateway: " + this._gatewayURL);
                this._raiseEvent("OnConnect", null);
            } else {
                if(this._verifyCount < 20){
                    this._verifyCount++;
                    this._setTimeout(this.Id + "._verifyConnection()", 1000);
                } else {
                    log.error("[" + this.Id + "]:  HttpJavaTunnelConfig was unable to verify to host: " + this._hostURL + " via gateway: " + this._gatewayURL);
                    throw this._newError("HttpJavaTunnelConfig connection verification failed.");
                }
            }
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  HttpJavaTunnelConfig suffered a fatal error attempting to verify the connection: " + e.message);
            this.connectError(e);
            return;
        }
    }

    /// <summary>
    /// Private method that polls the control every second to determine if the 
    /// connection is still viable.  If not, it raises the OnDisconnect event.
    /// </summary>
    this._pollConnection = _pollConnection;
    function _pollConnection(){
        if(this.isConnected()){
            this._setTimeout(this.Id + "._pollConnection()", 1000);
        } else {
            log.info("[" + this.Id + "]:  HttpJavaTunnelConfig connection poll returned a disconnected state.");
            this._raiseEvent("OnDisconnect", null);
        }
    }

    /// <summary>
    /// Method tells the TunnelConfig to attempt to disconnect.
    /// </summary>
    this.disconnect = _disconnect;
    function _disconnect(args) {
        this._connection.asyncStop();
        log.info("[" + this.Id + "]:  HttpJavaTunnelConfig successfully disconnected from host: " + this._hostURL + " via gateway: " + this._gatewayURL);
        // raise the OnDisconnect event, passing the results up the chain
        this._raiseEvent("OnDisconnect", args);
    }

    /// <summary>
    /// Method called by the TunnelConfig instance when a connection error has occurred.  Raises 
    /// an OnConnectError event.
    /// </summary>
    this.connectError = _connectError;
    function _connectError(error) {
        log.error("[" + this.Id + "]:  HttpJavaTunnelConfig failed to connect to host: " + this._hostURL + " via gateway: " + this._gatewayURL);
        // raise the OnConnectError event
        this._raiseEvent("OnConnectError", null);
    }

    /// <summary>
    /// Gets the local IPAddress of the TunnelConfig.
    /// </summary>
    /// <return type="string">the local IPAddress of the TunnelConfig</return>
    this.getDestinationIPAddress = _getDestinationIPAddress;
    function _getDestinationIPAddress() {
        try
        {
            var addr = this._connection.getLocalAddress();
            if (addr == null) {
                var ex = this._connection.getLastError();
                if (ex != null) {
                    throw this._newError("applet getLocalAddress() error: " + ex.getMessage());
                }
                else {
                    throw this._newError("applet getLocalAddress() returned null");
                }
            }
            return addr.getHostAddress();
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  HttpJavaTunnelConfig.getDestinationIPAddress() suffered a fatal error: " + e.message);
            throw this._newError("HttpJavaTunnelConfig connection does not return address: " + e.message);
        }
    }

    /// <summary>
    /// Gets the local Port of the TunnelConfig.
    /// </summary>
    this.getDestinationPort = _getDestinationPort;
    function _getDestinationPort() {
        try
        {
            var port = this._connection.getLocalPort();
            if (port == 0) {
                var ex = this._connection.getLastError();
                if (ex != null) {
                    throw this._newError("applet getLocalPort() error: " + ex.getMessage());
                }
                else {
                    throw this._newError("applet getLocalPort() returned 0");
                }
            }
            return port;
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  HttpJavaTunnelConfig.getDestinationPort() suffered a fatal error: " + e.message);
            throw this._newError("HttpJavaTunnelConfig connection does not return port: " + e.message);
        }
    }

    /// <summary>
    /// Checks the applet for whether it is connected.
    /// True/False indicates connection state; throws on connection error.
    /// </summary>
    this._checkConnected = _checkConnected;
    function _checkConnected(){
        try {
            var ret = this._connection.isStartedOk();
            if (ret >= 0) {
                return (ret > 0)? true : false;
            }
        }
        catch (e) {
            log.warn("[" + this.Id + "]:  HttpJavaTunnelConfig._checkConnected cannot verify applet isStartedOk()");
            return false;
        }
        // isStartedOk() returned error (<0)
        var errorMessage;
        try {
            errorMessage = this._connection.getLastError().getMessage();
        }
        catch (e) {
            errorMessage = "applet isStartedOk() returned error";
        }
        log.warn("[" + this.Id + "]:  HttpJavaTunnelConfig._checkConnected: applet error: " + errorMessage);
        throw this._newError(errorMessage);
    }

    /// <summary>
    /// Method determines if the control is actually connected or not, helpful for polling
    /// exercises and error checking in the URACoordinators.
    /// </summary>
    this.isConnected = _isConnected;
    function _isConnected(){
        try
        {
            if (this._checkConnected()) {
                log.info("[" + this.Id + "]:  HttpJavaTunnelConfig.isConnected returned: true");
                return true;
            }
            else {
                log.info("[" + this.Id + "]:  HttpJavaTunnelConfig.isConnected returned: false");
                return false;
            }
        }
        catch (e)
        {
            log.info("[" + this.Id + "]:  HttpJavaTunnelConfig.isConnected returned: false");
            return false;
        }
    }

    /// <summary>
    /// Method gets the ActiveX or Applet control of the TermClient depending upon what 
    /// ControlPlatform has been deployed.
    /// </summary>
    /// <return type="object">the internal control, if this control has not been properly
    /// initialized this method ***can return null***</return>
    this.getControl = _getControl;
    function _getControl(){
        return this._control;
    }
}

// register this instance with the TunnelConfigFactory
tunnelConfigFactory.registerTunnelConfig(ControlPlatform.Applet, TunnelConfigType.HTTPTunnel, "HttpJavaTunnelConfig");


/**********************************************************************
   $Author: dbabbitt $
   $Date: 2007/06/12 14:59:30 $
   $Revision: 1.18 $


   Copyright 2001 - 2007. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/
/// <summary>
/// Implementation class for the HttpsJavaTunnelConfig
/// </summary>
function HttpsJavaTunnelConfig (id){
/// region : inheritance --------------------------------------------
    this.base = TunnelConfig;
    this.base(id);
    log.info("[" + id + "]:  HttpsJavaTunnelConfig object created.");

/// region : private fields -----------------------------------------
    this._ctlSuffix = "_ax"; // the suffix applied to the HTML element Id
    this._protocol = "https://"; // the protocol scheme for this implementation

/// region : Properties ---------------------------------------------
    /// <summary>
    /// Gets/sets the name of the class that handles the upstream encoding.  This must be one of the following
    /// values:  "" or a comma delimited list of:  "OctetStreamUpHandler", "MultipartFormUpHandler" , "Base64UpHandler"
    /// </summary>   
    this.UpstreamHandler = "com.surgient.localproxy.connections.http.OctetStreamHandler$UpHandler,com.surgient.localproxy.connections.http.MultipartFormUpHandler,com.surgient.localproxy.connections.http.Base64Handler$UpHandler";
    
    /// <summary>
    /// Gets/sets the name of the class that handles the downstream encoding.  This must be one of the following
    /// values:  "" or a comma delimited list of:  "OctetStreamDnHandler", "Base64DnHandler"
    /// </summary>  
    this.DownstreamHandler = "com.surgient.localproxy.connections.http.OctetStreamHandler$DnHandler,com.surgient.localproxy.connections.http.Base64Handler$DnHandler";
 
/// region : Methods ------------------------------------------------

    /// <summary>
    /// Method renders the TunnelConfig's HTML to the target element's child nodes.  The method 
    /// of render varies for each implementation.
    /// </summary>
    this.renderHtml = _renderHtml;
    function _renderHtml() {
        var ctlid = this.Id + this._ctlSuffix;
        return '<applet id="' + ctlid + '" code="com.surgient.localproxy.applet.ProxyApplet.class" archive="' + appPath + '/URA/lib/LocalProxyApplet.jar"' + 
        ' height=0 width=0>' + 
        '<param name="logLevel" value=5>' + 
        '<param name=cabbase value="' + appPath + '/URA/lib/LocalProxyApplet11.cab">' + 
        '</applet>';
    }

    /// <summary>
    /// Method tells the TunnelConfig to attempt to start the remote session. Raises 
    /// an OnConnect event.
    /// </summary>
    this.connect = _connect;
    function _connect(){
        try{
            // get the ref to the HTML element
            if(this._control == null){
                this._control = this.Element.getElementById(this.Id + this._ctlSuffix);
                if(this._control == null){
                    log.error("[" + this.Id + "]:  HttpsJavaTunnelConfig unable to find rendered object tag in document.");
                    throw this._newError("Unable to target control HTML tag");
                }
            }
            log.debug("[" + this.Id + "]:  HttpsJavaTunnelConfig._control = " + this._control.tagName);
            
            try
            {
            	// the isStarted method is a simple boolean test, the results of which don't matter 
                // at this point, to verify that the control has been loaded properly this method just 
                // needs to return a value and not throw an exception because the method is not supported.
                if(this._control.isStarted()){
                    log.info("[" + this.Id + "]:  HttpsJavaTunnelConfig attempting to connect to host: " + this.HostAddress + ":" + this.HostPort + 
                        " via gateway: " + this.GatewayAddress);
                    this._connectCount = 0;

                    // create the connection object using the destination address
                    if(this.HostAddress != ""){
                        if(this.HostPort != ""){
                            this._hostURL = this.HostProtocol + "://" + this.HostAddress + ":" + this.HostPort;
                        } else {
                            this._hostURL = this.HostProtocol + "://" + this.HostAddress;
                        }
                        log.info("[" + this.Id + "]:  HttpsJavaTunnelConfig establishing connection to host: " + this._hostURL);
                        this._connection = this._control.newConnection(this._hostURL);
                    } else {
                        log.error("[" + this.Id + "]:  HttpsJavaTunnelConfig.HostAddress property is invalid and cannot be connected.");
                        throw this._newError("HostAddress property is invalid.");
                    }

                    // set the GatewayBaseUrl on the control
                    // note: port override is not allowed
                    if(this.GatewayAddress != ""){
                        this._gatewayURL = this._protocol + this.GatewayAddress + this._gatewayName;
                        log.info("[" + this.Id + "]:  HttpsJavaTunnelConfig establishing connection to gateway: " + this._gatewayURL);
                        this._connection.getPropertyBag().setProperty("HttpVirtualConnection.GatewayBaseUrl", this._gatewayURL);
                    } else {
                        log.error("[" + this.Id + "]:  HttpsJavaTunnelConfig.GatewayAddress address is invalid and cannot be connected.");
                        throw this._newError("GatewayAddress address is invalid.");
                    }

                    // set the connection classname
                    this._connection.getPropertyBag().setProperty("ProxyConnection.connectionClasses", "com.surgient.localproxy.connections.http.HttpVirtualConnection");

                    // set the upstream handler class
                    if(this.UpsteamHandler != ""){
                        this._connection.getPropertyBag().setProperty("HttpVirtualConnection.upstreamClasses", this.UpstreamHandler);
                    }

                    if(this.DownstreamHandler != ""){
                        this._connection.getPropertyBag().setProperty("HttpVirtualConnection.downstreamClasses", this.DownstreamHandler);
                    }

                    // now try to start the connection
                    this._connection.asyncStart();

                    // finally set up a callback to verify the connection was made
                    this._setTimeout(this.Id + "._verifyConnection()", 1000);                    
                } else {
                    throw this._newError("No isStarted method");
                }
            }
            catch (ex)
            {
                log.debug("[" + this.Id + "]:  HttpsJavaTunnelConfig control error while trying to start: " + ex.message);
                // on numerous failures to start connecting, raise OnLoadError
                if(this._connectCount < 25){
                    // the applet is not yet ready, so re-call this function after a set timeout
                    this._setTimeout(this.Id + ".connect()", 1000);
                    this._connectCount++;
                } else {
                    log.fatal("[" + this.Id + "]:  HttpsJavaTunnelConfig control unable to initialize due to a download or installation error.");
                    // raise an OnLoadError event
                    this._raiseEvent("OnLoadError", null);
                }
            }
        } catch(e){
            log.fatal("[" + this.Id + "]:  HttpsJavaTunnelConfig suffered a fatal error during the connect() method: " + e.message);
            this.connectError(e);
            return;
        }
    }

    /// <summary>
    /// Private method to verify the TunnelConfig's connection before raising the OnConnect event.
    /// </summary>    
    this._verifyConnection = _verifyConnection;
    function _verifyConnection(){
        try
        {
            if(this._connection == null){
                log.error("[" + this.Id + "]:  HttpsJavaTunnelConfig control's Connection object was uninstantiated.");
                throw this._newError("Connection was uninstantiated in Applet control.");
            }
            if(this._checkConnected()){
                log.info("[" + this.Id + "]:  HttpsJavaTunnelConfig successfully connected to host: " + this._hostURL + " via gateway: " + this._gatewayURL);
                this._raiseEvent("OnConnect", null);
            } else {
                if(this._verifyCount < 20){
                    this._verifyCount++;
                    this._setTimeout(this.Id + "._verifyConnection()", 1000);
                } else {
                    log.error("[" + this.Id + "]:  HttpsJavaTunnelConfig was unable to verify to host: " + this._hostURL + " via gateway: " + this._gatewayURL);
                    throw this._newError("HttpsJavaTunnelConfig connection verification failed.");
                }
            }
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  HttpsJavaTunnelConfig suffered a fatal error attempting to verify the connection: " + e.message);
            this.connectError(e);
            return;
        }
    }

    /// <summary>
    /// Private method that polls the control every second to determine if the 
    /// connection is still viable.  If not, it raises the OnDisconnect event.
    /// </summary>
    this._pollConnection = _pollConnection;
    function _pollConnection(){
        if(this.isConnected()){
            this._setTimeout(this.Id + "._pollConnection()", 1000);
        } else {
            log.info("[" + this.Id + "]:  HttpsJavaTunnelConfig connection poll returned a disconnected state.");
            this._raiseEvent("OnDisconnect", null);
        }
    }

    /// <summary>
    /// Method tells the TunnelConfig to attempt to disconnect.
    /// </summary>
    this.disconnect = _disconnect;
    function _disconnect(args) {
        this._connection.asyncStop();
        log.info("[" + this.Id + "]:  HttpsJavaTunnelConfig successfully disconnected from host: " + this._hostURL + " via gateway: " + this._gatewayURL);
        // raise the OnDisconnect event, passing the results up the chain
        this._raiseEvent("OnDisconnect", args);
    }

    /// <summary>
    /// Method called by the TunnelConfig instance when a connection error has occurred.  Raises 
    /// an OnConnectError event.
    /// </summary>
    this.connectError = _connectError;
    function _connectError(error) {
        log.error("[" + this.Id + "]:  HttpsJavaTunnelConfig failed to connect to host: " + this._hostURL + " via gateway: " + this._gatewayURL);
        // raise the OnConnectError event
        this._raiseEvent("OnConnectError", null);
    }

    /// <summary>
    /// Gets the local IPAddress of the TunnelConfig.
    /// </summary>
    /// <return type="string">the local IPAddress of the TunnelConfig</return>
    this.getDestinationIPAddress = _getDestinationIPAddress;
    function _getDestinationIPAddress() {
        try
        {
            var addr = this._connection.getLocalAddress();
            if (addr == null) {
                var ex = this._connection.getLastError();
                if (ex != null) {
                    throw this._newError("applet getLocalAddress() error: " + ex.getMessage());
                }
                else {
                    throw this._newError("applet getLocalAddress() returned null");
                }
            }
            return addr.getHostAddress();
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  HttpsJavaTunnelConfig.getDestinationIPAddress() suffered a fatal error: " + e.message);
            throw this._newError("HttpsJavaTunnelConfig connection does not return address: " + e.message);
        }
    }

    /// <summary>
    /// Gets the local Port of the TunnelConfig.
    /// </summary>
    this.getDestinationPort = _getDestinationPort;
    function _getDestinationPort() {
        try
        {
            var port = this._connection.getLocalPort();
            if (port == 0) {
                var ex = this._connection.getLastError();
                if (ex != null) {
                    throw this._newError("applet getLocalPort() error: " + ex.getMessage());
                }
                else {
                    throw this._newError("applet getLocalPort() returned 0");
                }
            }
            return port;
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  HttpsJavaTunnelConfig.getDestinationPort() suffered a fatal error: " + e.message);
            throw this._newError("HttpsJavaTunnelConfig connection does not return port: " + e.message);
        }
    }

    /// <summary>
    /// Checks the applet for whether it is connected.
    /// True/False indicates connection state; throws on connection error.
    /// </summary>
    this._checkConnected = _checkConnected;
    function _checkConnected(){
        try {
            var ret = this._connection.isStartedOk();
            if (ret >= 0) {
                return (ret > 0)? true : false;
            }
        }
        catch (e) {
            log.warn("[" + this.Id + "]:  HttpsJavaTunnelConfig._checkConnected cannot verify applet isStartedOk()");
            return false;
        }
        // isStartedOk() returned error (<0)
        var errorMessage;
        try {
            errorMessage = this._connection.getLastError().getMessage();
        }
        catch (e) {
            errorMessage = "applet isStartedOk() returned error";
        }
        log.warn("[" + this.Id + "]:  HttpsJavaTunnelConfig._checkConnected: applet error: " + errorMessage);
        throw this._newError(errorMessage);
    }

    /// <summary>
    /// Method determines if the control is actually connected or not, helpful for polling
    /// exercises and error checking in the URACoordinators.
    /// </summary>
    this.isConnected = _isConnected;
    function _isConnected(){
        try
        {
            if (this._checkConnected()) {
                log.info("[" + this.Id + "]:  HttpsJavaTunnelConfig.isConnected returned: true");
                return true;
            }
            else {
                log.info("[" + this.Id + "]:  HttpsJavaTunnelConfig.isConnected returned: false");
                return false;
            }
        }
        catch (e)
        {
            log.info("[" + this.Id + "]:  HttpsJavaTunnelConfig.isConnected returned: false");
            return false;
        }
    }

    /// <summary>
    /// Method gets the ActiveX or Applet control of the TermClient depending upon what 
    /// ControlPlatform has been deployed.
    /// </summary>
    /// <return type="object">the internal control, if this control has not been properly
    /// initialized this method ***can return null***</return>
    this.getControl = _getControl;
    function _getControl(){
        return this._control;
    }
}

// register this instance with the TunnelConfigFactory
tunnelConfigFactory.registerTunnelConfig(ControlPlatform.Applet, TunnelConfigType.HTTPSTunnel, "HttpsJavaTunnelConfig");


/**********************************************************************
   $Author: greynold $
   $Date: 2006/04/17 20:24:00 $
   $Revision: 1.7 $


   Copyright 2001 - 2004. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/
/// <summary>
/// Implementation class for the NoOpJavaTunnelConfig
/// </summary>
function NoOpJavaTunnelConfig (id){
/// region : inheritance --------------------------------------------
    this.base = TunnelConfig;
    this.base(id);
    log.info("[" + id + "]:  NoOpJavaTunnelConfig object created.");

/// region : private fields -----------------------------------------
    this._ctlSuffix = ""; // the suffix applied to the HTML element Id
    this._protocol = ""; // the protocol scheme for this implementation

/// region : Properties ---------------------------------------------
 
/// region : Methods ------------------------------------------------

    /// <summary>
    /// Method renders the TunnelConfig's HTML to the target element's child nodes.  The method 
    /// of render varies for each implementation.
    /// </summary>
    this.renderHtml = _renderHtml;
    function _renderHtml() {
        return '';
    }

    /// <summary>
    /// Method tells the TunnelConfig to attempt to start the remote session. Raises 
    /// an OnConnect event.
    /// </summary>
    this.connect = _connect;
    function _connect(){
        log.info("[" + this.Id + "]:  NoOpJavaTunnelConfig attempting to connect to host: " + this.HostAddress + ":" + this.HostPort + 
            " via direct connection.");
        // set up a callback to verify the connection was made, this releases the browser
        // from the thread and allows it to process the document writes done by the URACoordinator
                this._setTimeout(this.Id + "._verifyConnection()", 1000);
    }

    /// <summary>
    /// Private method to verify the TunnelConfig's connection before raising the OnConnect event.
    /// </summary>    
    this._verifyConnection = _verifyConnection;
    function _verifyConnection(){
        log.info("[" + this.Id + "]:  NoOpJavaTunnelConfig successfully connected to host: " + this.HostAddress + ":" + this.HostPort + 
            " via direct connection.");
        this._raiseEvent("OnConnect", null);
    }

    /// <summary>
    /// Private method that polls the control every second to determine if the 
    /// connection is still viable.  If not, it raises the OnDisconnect event.
    /// </summary>
    this._pollConnection = _pollConnection;
    function _pollConnection(){
        return;
    }

    /// <summary>
    /// Method tells the TunnelConfig to attempt to disconnect.
    /// </summary>
    this.disconnect = _disconnect;
    function _disconnect(args) {
        log.info("[" + this.Id + "]:  NoOpJavaTunnelConfig successfully disconnected from host: " + this.HostAddress + ":" + this.HostPort + 
            " via direct connection.");
        this._raiseEvent("OnDisconnect", args);
    }

    /// <summary>
    /// Method called by the TunnelConfig instance when a connection error has occurred.  Raises 
    /// an OnConnectError event.
    /// </summary>
    this.connectError = _connectError;
    function _connectError(error) {
        log.error("[" + this.Id + "]:  NoOpJavaTunnelConfig failed to connect to host: " + this.HostAddress + ":" + this.HostPort + 
            " via direct connection with the following error: " + error);
        this._raiseEvent("OnConnectError", error.message);
    }

    /// <summary>
    /// Gets the local IPAddress of the TunnelConfig.
    /// </summary>
    /// <return type="string">the local IPAddress of the TunnelConfig</return>
    this.getDestinationIPAddress = _getDestinationIPAddress;
    function _getDestinationIPAddress() {
        return this.HostAddress;
    }

    /// <summary>
    /// Gets the local Port of the TunnelConfig.
    /// </summary>
    this.getDestinationPort = _getDestinationPort;
    function _getDestinationPort() {
        return this.HostPort;
    }

    /// <summary>
    /// Method determines if the control is actually connected or not, helpful for polling 
    /// exercises and error checking in the URACoordinators.
    /// </summary>
    this.isConnected = _isConnected;
    function _isConnected(){
        log.info("[" + this.Id + "]:  NoOpJavaTunnelConfig.isConnected returned: true");
        return true;
    }

    /// <summary>
    /// Method gets the ActiveX or Applet control of the TermClient depending upon what 
    /// ControlPlatform has been deployed.
    /// </summary>
    /// <return type="object">the internal control, if this control has not been properly
    /// initialized this method ***can return null***</return>
    this.getControl = _getControl;
    function _getControl(){
        return new Object();
    }
}

// register this instance with the TunnelConfigFactory
tunnelConfigFactory.registerTunnelConfig(ControlPlatform.Applet, TunnelConfigType.NoOpTunnel, "NoOpJavaTunnelConfig");


/**********************************************************************
   $Author: dbabbitt $
   $Date: 2007/06/12 14:59:30 $
   $Revision: 1.3 $


   Copyright 2001 - 2007. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/
/// <summary>
/// Implementation class for the SocketProxyJavaTunnelConfig
/// </summary>
function SocketProxyJavaTunnelConfig (id){
/// region : inheritance --------------------------------------------
    this.base = TunnelConfig;
    this.base(id);
    log.info("[" + id + "]:  SocketProxyJavaTunnelConfig object created.");

/// region : private fields -----------------------------------------
    this._ctlSuffix = "_ax"; // the suffix applied to the HTML element Id
    this._protocol = "tcp://"; // the protocol scheme for this implementation

/// region : Properties ---------------------------------------------
 
/// region : Methods ------------------------------------------------

    /// <summary>
    /// Method renders the TunnelConfig's HTML to the target element's child nodes.  The method 
    /// of render varies for each implementation.
    /// </summary>
    this.renderHtml = _renderHtml;
    function _renderHtml() {
        var ctlid = this.Id + this._ctlSuffix;
        return '<applet id="' + ctlid + '" code="com.surgient.localproxy.applet.ProxyApplet.class" archive="' + appPath + '/URA/lib/LocalProxyApplet.jar"' + 
        ' height="0" width="0">' + 
        '<param name="logLevel" value="5" />' + 
        '<param name="cabbase" value="' + appPath + '/URA/lib/LocalProxyApplet11.cab" />' + 
        '</applet>';
    }

    /// <summary>
    /// Method tells the TunnelConfig to attempt to start the remote session. Raises 
    /// an OnConnect event.
    /// </summary>
    this.connect = _connect;
    function _connect(){
        try{
            // get the ref to the HTML element
            if(this._control == null){
                this._control = this.Element.getElementById(this.Id + this._ctlSuffix);
                if(this._control == null){
                    log.error("[" + this.Id + "]:  SocketProxyJavaTunnelConfig unable to find rendered object tag in document.");
                    throw this._newError("Unable to target control HTML tag");
                }
            }
            log.debug("[" + this.Id + "]:  SocketProxyJavaTunnelConfig._control = " + this._control.tagName);
            
            try
            {
            	// the isStarted method is a simple boolean test, the results of which don't matter 
                // at this point, to verify that the control has been loaded properly this method just 
                // needs to return a value and not throw an exception because the method is not supported.
                if(this._control.isStarted()){
                    log.info("[" + this.Id + "]:  SocketProxyJavaTunnelConfig attempting to connect to host: " + this.HostAddress + ":" + this.HostPort + 
                        " via gateway: " + this.GatewayAddress);
                    this._connectCount = 0;

                    // create the connection object using the destination address
                    if(this.HostAddress != ""){
                        if(this.HostPort != ""){
                            this._hostURL = this.HostProtocol + "://" + this.HostAddress + ":" + this.HostPort;
                        } else {
                            this._hostURL = this.HostProtocol + "://" + this.HostAddress;
                        }
                        log.info("[" + this.Id + "]:  SocketProxyJavaTunnelConfig establishing connection to host: " + this._hostURL);
                        this._connection = this._control.newConnection(this._hostURL);
                    } else {
                        log.error("[" + this.Id + "]:  SocketProxyJavaTunnelConfig.HostAddress property is invalid and cannot be connected.");
                        throw this._newError("HostAddress property is invalid.");
                    }

                    // set the Gateway IP address (and port, optionally)
                    if(this.GatewayAddress != ""){
                        if(this.GatewayPort != ""){
                            this._gatewayURL = this._protocol + this.GatewayAddress + ":" + this.GatewayPort;
                        } else {
                            this._gatewayURL = this._protocol + this.GatewayAddress;
                        }
                        log.info("[" + this.Id + "]:  SocketProxyJavaTunnelConfig establishing connection to gateway: " + this._gatewayURL);
                        this._connection.getPropertyBag().setProperty("SocketProxyConnection.Gateway", this.GatewayAddress);
                        if(this.GatewayPort != ""){
                            this._connection.getPropertyBag().setProperty("SocketProxyConnection.GatewayPort", this.GatewayPort);
                        }
                    } else {
                        log.error("[" + this.Id + "]:  SocketProxyJavaTunnelConfig.GatewayAddress address is invalid and cannot be connected.");
                        throw this._newError("GatewayAddress address is invalid.");
                    }

                    // set the connection classname
                    this._connection.getPropertyBag().setProperty("ProxyConnection.connectionClasses", "com.surgient.localproxy.connections.socketproxy.SocketProxyConnection");

                    // now try to start the connection
                    this._connection.asyncStart();

                    // finally set up a callback to verify the connection was made
                    this._setTimeout(this.Id + "._verifyConnection()", 1000);                    
                } else {
                    throw this._newError("No isStarted method");
                }
            }
            catch (ex)
            {
                log.debug("[" + this.Id + "]:  SocketProxyJavaTunnelConfig control error while trying to start: " + ex.message);
                // on numerous failures to start connecting, raise OnLoadError
                if(this._connectCount < 25){
                    // the applet is not yet ready, so re-call this function after a set timeout
                    this._setTimeout(this.Id + ".connect()", 1000);
                    this._connectCount++;
                } else {
                    log.fatal("[" + this.Id + "]:  SocketProxyJavaTunnelConfig control unable to initialize due to a download or installation error.");
                    // raise an OnLoadError event
                    this._raiseEvent("OnLoadError", null);
                }
            }
        } catch(e){
            log.fatal("[" + this.Id + "]:  SocketProxyJavaTunnelConfig suffered a fatal error during the connect() method: " + e.message);
            this.connectError(e);
            return;
        }
    }

    /// <summary>
    /// Private method to verify the TunnelConfig's connection before raising the OnConnect event.
    /// </summary>    
    this._verifyConnection = _verifyConnection;
    function _verifyConnection(){
        try
        {
            if(this._connection == null){
                log.error("[" + this.Id + "]:  SocketProxyJavaTunnelConfig control's Connection object was uninstantiated.");
                throw this._newError("Connection was uninstantiated in Applet control.");
            }
            if(this._checkConnected()){
                log.info("[" + this.Id + "]:  SocketProxyJavaTunnelConfig successfully connected to host: " + this._hostURL + " via gateway: " + this._gatewayURL);
                this._raiseEvent("OnConnect", null);
            } else {
                if(this._verifyCount < 20){
                    this._verifyCount++;
                    this._setTimeout(this.Id + "._verifyConnection()", 1000);
                } else {
                    log.error("[" + this.Id + "]:  SocketProxyJavaTunnelConfig was unable to verify to host: " + this._hostURL + " via gateway: " + this._gatewayURL);
                    throw this._newError("SocketProxyJavaTunnelConfig connection verification failed.");
                }
            }
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  SocketProxyJavaTunnelConfig suffered a fatal error attempting to verify the connection: " + e.message);
            this.connectError(e);
            return;
        }
    }

    /// <summary>
    /// Private method that polls the control every second to determine if the 
    /// connection is still viable.  If not, it raises the OnDisconnect event.
    /// </summary>
    this._pollConnection = _pollConnection;
    function _pollConnection(){
        if(this.isConnected()){
            this._setTimeout(this.Id + "._pollConnection()", 1000);
        } else {
            log.info("[" + this.Id + "]:  SocketProxyJavaTunnelConfig connection poll returned a disconnected state.");
            this._raiseEvent("OnDisconnect", null);
        }
    }

    /// <summary>
    /// Method tells the TunnelConfig to attempt to disconnect.
    /// </summary>
    this.disconnect = _disconnect;
    function _disconnect(args) {
        this._connection.asyncStop();
        log.info("[" + this.Id + "]:  SocketProxyJavaTunnelConfig successfully disconnected from host: " + this._hostURL + " via gateway: " + this._gatewayURL);
        // raise the OnDisconnect event, passing the results up the chain
        this._raiseEvent("OnDisconnect", args);
    }

    /// <summary>
    /// Method called by the TunnelConfig instance when a connection error has occurred.  Raises 
    /// an OnConnectError event.
    /// </summary>
    this.connectError = _connectError;
    function _connectError(error) {
        log.error("[" + this.Id + "]:  SocketProxyJavaTunnelConfig failed to connect to host: " + this._hostURL + " via gateway: " + this._gatewayURL);
        // raise the OnConnectError event
        this._raiseEvent("OnConnectError", null);
    }

    /// <summary>
    /// Gets the local IPAddress of the TunnelConfig.
    /// </summary>
    /// <return type="string">the local IPAddress of the TunnelConfig</return>
    this.getDestinationIPAddress = _getDestinationIPAddress;
    function _getDestinationIPAddress() {
        try
        {
            var addr = this._connection.getLocalAddress();
            if (addr == null) {
                var ex = this._connection.getLastError();
                if (ex != null) {
                    throw this._newError("applet getLocalAddress() error: " + ex.getMessage());
                }
                else {
                    throw this._newError("applet getLocalAddress() returned null");
                }
            }
            return addr.getHostAddress();
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  SocketProxyJavaTunnelConfig.getDestinationIPAddress() suffered a fatal error: " + e.message);
            throw this._newError("SocketProxyJavaTunnelConfig connection does not return address: " + e.message);
        }
    }

    /// <summary>
    /// Gets the local Port of the TunnelConfig.
    /// </summary>
    this.getDestinationPort = _getDestinationPort;
    function _getDestinationPort() {
        try
        {
            var port = this._connection.getLocalPort();
            if (port == 0) {
                var ex = this._connection.getLastError();
                if (ex != null) {
                    throw this._newError("applet getLocalPort() error: " + ex.getMessage());
                }
                else {
                    throw this._newError("applet getLocalPort() returned 0");
                }
            }
            return port;
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  SocketProxyJavaTunnelConfig.getDestinationPort() suffered a fatal error: " + e.message);
            throw this._newError("SocketProxyJavaTunnelConfig connection does not return port: " + e.message);
        }
    }

    /// <summary>
    /// Checks the applet for whether it is connected.
    /// True/False indicates connection state; throws on connection error.
    /// </summary>
    this._checkConnected = _checkConnected;
    function _checkConnected(){
        try {
            var ret = this._connection.isStartedOk();
            if (ret >= 0) {
                return (ret > 0)? true : false;
            }
        }
        catch (e) {
            log.warn("[" + this.Id + "]:  SocketProxyJavaTunnelConfig._checkConnected cannot verify applet isStartedOk()");
            return false;
        }
        // isStartedOk() returned error (<0)
        var errorMessage;
        try {
            errorMessage = this._connection.getLastError().getMessage();
        }
        catch (e) {
            errorMessage = "applet isStartedOk() returned error";
        }
        log.warn("[" + this.Id + "]:  SocketProxyJavaTunnelConfig._checkConnected: applet error: " + errorMessage);
        throw this._newError(errorMessage);
    }

    /// <summary>
    /// Method determines if the control is actually connected or not, helpful for polling
    /// exercises and error checking in the URACoordinators.
    /// </summary>
    this.isConnected = _isConnected;
    function _isConnected(){
        try
        {
            if (this._checkConnected()) {
                log.info("[" + this.Id + "]:  SocketProxyJavaTunnelConfig.isConnected returned: true");
                return true;
            }
            else {
                log.info("[" + this.Id + "]:  SocketProxyJavaTunnelConfig.isConnected returned: false");
                return false;
            }
        }
        catch (e)
        {
            log.info("[" + this.Id + "]:  SocketProxyJavaTunnelConfig.isConnected returned: false");
            return false;
        }
    }
    
    /// <summary>
    /// Method gets the ActiveX or Applet control of the TermClient depending upon what 
    /// ControlPlatform has been deployed.
    /// </summary>
    /// <return type="object">the internal control, if this control has not been properly
    /// initialized this method ***can return null***</return>
    this.getControl = _getControl;
    function _getControl(){
        return this._control;
    }
}

// register this instance with the TunnelConfigFactory
tunnelConfigFactory.registerTunnelConfig(ControlPlatform.Applet, TunnelConfigType.SocketProxy, "SocketProxyJavaTunnelConfig");


/**********************************************************************
   $Author: csanford $
   $Date: 2008/08/06 22:13:34 $
   $Revision: 1.44 $


   Copyright 2001 - 2007. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/
/// <summary>
/// URAConnectionStates struct defines the available connection states for  
/// the URACoordinator object.
/// </summary>
URAConnectionStates = {
    /// <summary>
    /// Sets ConnectionState as Disconnected.
    /// </summary>
    Disconnected : 0,
    /// <summary>
    /// Sets ConnectionState as Connecting.  Set once the connection
    /// process has started but not completed.
    /// </summary>
    Connecting : 1,
    /// <summary>
    /// Sets ConnectionState as Connected. Set once the connection 
    /// process has successfully completed.
    /// </summary>
    Connected : 2,
    /// <summary>
    /// Sets ConnectionState as ConnectionError. Set once the connection 
    /// process has failed to find a successful connection.
    /// </summary>
    ConnectionError : 3
};

function URACoordinator (id, iFrameName, configSettings){
/// region : inheritance --------------------------------------------
    this.base = BaseObject;
    this.base(id);
    log.info("[" + id + "]:  URACoordinator object created.");
    
/// region : private fields -----------------------------------------
    this._activeTermClientConfig = null;
    this._activeTunnelConfigSetting = null;
    this._configSettings = configSettings;
    this._currentConfigSetting = 0;
    this._loadFailSafe = 60000; // number of milliseconds to wait for a control to connect before it is re-rendered
    // configuration fields
    this._hostAddress = "";
    this._hostPort = "";
    this._gatewayAddress = "";
    this._gatewayPort = "";
    // dhtml fields
    this._termClientTargetId = "__tmc";
    this._tunnelConfigTargetId = "__tc";
    this._termClientTarget = null;
    this._tunnelConfigTarget = null;



/// region : Properties ---------------------------------------------

    /// <summary>
    /// Gets/sets the state of the connection.
    /// </summary>
    this.ConnectionState = URAConnectionStates.Disconnected;

    /// <summary>
    /// Gets/sets the active TermClient.
    /// </summary>
    this.ActiveTermClient = null;
    
    /// <summary>
    /// Gets/sets the active TunnelConfig.
    /// </summary>
    this.ActiveTunnelConfig = null;

    /// <summary>
    /// Gets/sets the active URAConfigSetting.  If no viable config
    /// setting is found during the connection attempt, this value 
    /// is set back to null.
    /// </summary>
    this.ActiveConfigSetting = null;

    /// <summary>
    /// Gets/sets the name of the target frame to render to.
    /// </summary>
    this.TargetFrameName = iFrameName;

    /// <summary>
    /// Gets/sets the reference to the target frame
    /// </summary>
    this.TargetFrame = null;
 
    /// <summary>
    /// Gets/sets the minimum height of the TermClient control.
    /// </summary>
    this.MinHeight = 600;

    /// <summary>
    /// Gets/sets the minimum width of the TermClient control.
    /// </summary>
    this.MinWidth = 800;

    /// <summary>
    /// Gets/sets the UserName for the TermClient control.
    /// </summary>
    this.Username = "";

    /// <summary>
    /// Gets/sets the Password for the TermClient control.
    /// </summary>
    this.Password = "";

    /// <summary>
    /// Gets/sets the Username required to authenticate via the TermClient's protocol.
    /// </summary>
    this.ProtocolUsername = "";

    /// <summary>
    /// Gets/sets the Password required to authenticate via the TermClient's protocol.
    /// </summary>
    this.ProtocolPassword = "";

    /// <summary>
    /// Gets/sets the Username required to authenticate on the vm's Host.
    /// </summary>
    this.HostUsername = "";

    /// <summary>
    /// Gets/sets the Password required to authenticate on the vm's Host.
    /// </summary>
    this.HostPassword = "";

    /// <summary>
    /// Gets/sets the type of virtualization host.
    /// </summary>
    this.HostType = "";

    /// <summary>
    /// Gets/sets the version of virtualization host platform.
    /// </summary>
    this.HostVersion = "";

    /// <summary>
    /// Gets/sets the name of the VM for the console TermClient control.
    /// </summary>
    this.VmName = "";

    /// <summary>
    /// Gets/sets the name of the file for the console TermClient control.
    /// </summary>
    this.VmFile = "";

    /// <summary>
    /// Gets/sets the local flag marking whether or not an OnConnectError method was raised
    /// during the cycling of ConfigSettings.
    /// </summary>
    this.ConnectErrorOccurred = false;

    /// <summary>
    /// Gets/sets the local flag marking whether or not an OnLoadError method was raised
    /// during the cycling of ConfigSettings.
    /// </summary>
    this.LoadErrorOccurred = false;
   

/// region : Methods ------------------------------------------------
    /// <summary>
    /// Method which returns the height of the TermClient control using 
    /// the following algorithm:  if the height of the IFrame is 
    /// larger than this.MinHeight, that height is used, else this.MinHeight 
    /// is used.
    /// </summary>
    this._getTargetHeight = _getTargetHeight;
    function _getTargetHeight(){
        var iFrameElm = document.getElementById(this.TargetFrameName);
        var curHeight = iFrameElm.clientHeight;
        if(curHeight > this.MinHeight){
            return curHeight;
        } else {
            return this.MinHeight;
        }
    }

    /// <summary>
    /// Method which returns the width of the TermClient control using 
    /// the following algorithm:  if the width of the IFrame is 
    /// larger than this.MinWidth, that width is used, else this.MinWidth 
    /// is used.
    /// </summary>
    this._getTargetWidth = _getTargetWidth;
    function _getTargetWidth(){
        var iFrameElm = document.getElementById(this.TargetFrameName);
        var curWidth = iFrameElm.clientWidth;
        if(curWidth > this.MinWidth){
            return curWidth;
        } else {
            return this.MinWidth;
        }
    }

    /// <summary>
    /// Noop function alerts that calling methods aren't implemented.
    /// </summary>
    function _noop(caller){
        alert(caller + ' method has not been implemented.');
    }

    /// <summary>
    /// Sets the array of URAConfigSettings.
    /// </summary>
    /// <param name="configSettings">array of <see cref="URAConfigSetting"/> settings to use</param>
    this.setConfigSettings = _setConfigSettings;
    function _setConfigSettings(configSettings){
        log.debug("[" + this.Id + "]:  URACoordinator configSettings set.");
        this._configSettings = configSettings;
    }

    /// <summary>
    /// Initialization method for the object.  Sets up the object and initiaites the attempts 
    /// to instantiate and connect to the <see cref="TunnelConfig"/> and <see cref="TermClient"/> 
    /// that will be used by the object.
    /// </summary>
    /// <param type="string" name="hostAddress">the ip address of the remote host</param>
    /// <param type="int" name="hostPort">port to connect to the remote host on</param>
    /// <param type="string" name="gatewayAddress">the ip address of the gateway server</param>
    /// <param type="int" name="gatewayPort">port to connect to the gateway server on *** can be empty 
    /// string value***</param>
    /// <param type="string" name="protocolUsername">the username required to authenticate over a 
    /// TermClient protocol</param>
    /// <param type="string" name="protocolPassword">the password required to authenticate over a 
    /// TermClient protocol</param>
    /// <param type="string" name="vmName">the name of the vm to connect to if the TermClient has 
    /// console access</param>
    this.init = _init;
    function _init(username, password, gatewayAddress, gatewayPort, protocolUsername, protocolPassword, vmName, vmFile, hostUsername, hostPassword, hostType, hostVersion){
        try
        {
            // set the private properties
            this._gatewayAddress = gatewayAddress;
            if(typeof(gatewayPort) != "undefined"){
                if(gatewayPort != ""){
                    this._gatewayPort = gatewayPort;
                }
            }
            log.info("[" + this.Id + "]:  URACoordinator initialized using the following parameters:  " +
                "Username: " + username + ", " +
                "Password: " + password +  ", " +
                "GatewayAddress: " + gatewayAddress + ", " +
                "GatewayPort: " + gatewayPort + ", " +
                "ProtocolUsername: " + protocolUsername + ", " +
                "ProtocolPassword: " + protocolPassword + ", " +
                "VMName: " + vmName + ", " + 
                "VMFile: " + vmFile + ", " + 
                "HostUsername: " + hostUsername + ", " +
                "HostPassword: " + hostPassword + ", " + 
                "HostType: " + hostType + ", " + 
                "HostVersion: " + hostVersion
            );
            
            // set the Username and Password properties
            this.Username = username;
            this.Password = password;

            // set the protocol's Username and Password properties
            if(typeof(protocolUsername) != "undefined"){
                this.ProtocolUsername = protocolUsername;
            }
            if(typeof(protocolPassword) != "undefined"){
                this.ProtocolPassword = protocolPassword;
            }

            // set the vm name property 
            if(typeof(vmName) != "undefined"){
                this.VmName = vmName;
            }

            if(typeof(vmFile) != "undefined"){
                this.VmFile = vmFile;
            }

            if(typeof(hostUsername) != "undefined"){
                this.HostUsername = hostUsername;
            }

            if(typeof(hostPassword) != "undefined"){
                this.HostPassword = hostPassword;
            }

            if(typeof(hostType) != "undefined"){
                this.HostType = hostType;
            }
        
            if(typeof(hostVersion) != "undefined"){
                this.HostVersion = hostVersion;
            }

            // get the target IFrame reference
            if(this.TargetFrame == null){
                this.TargetFrame = window.frames[iFrameName];
            }

            this.readyCount = 0;
        }
        catch (e)
        {
            log.fatal("[" + this.Id + "]:  URACoordinator sufferred a fatal during the init method:  " + e.message);
            return;
        }
    }

    /// <summary>
    /// Method attempts to instantiate the TunnelConfig and then the TermClient javascript 
    /// controls and kicks off the process for rendering the ActiveX/Applet tags to the 
    /// appropriate HTML element.  the connect() method starts off a recursive process wherein 
    /// the specified configuration settings are tried one after another until either one 
    /// successfully connects or the list has been completely run through.  In the case of 
    /// total connection failure the URACoordinator.OnConnectError() event method will be raised.
    /// </summary>
    this.connect = _connect;
    function _connect(){
        this.ConnectionState = URAConnectionStates.Connecting;
        try
        {
            var configlog = "";
            for(var i = 0; i < this._configSettings.length; i++){
                configlog += "[" + i +"] = [ControlPlatform:" + this._configSettings[i].ControlPlatform + ", TermClientType:" + 
                    this._configSettings[i].TermClientType + ", TunnelConfigType:" + this._configSettings[i].TunnelConfigType + 
                    ", HostAddress:" + this._configSettings[i].HostAddress + ", HostPort:" + this._configSettings[i].HostPort + "]\n";
            }
            log.info("[" + this.Id + "]:  URACoordinator initialized with the following config settings:\n" + configlog);
            log.info("[" + this.Id + "]:  URACoordinator attempting new connection.");
            // try to instantiate the controls based on the 
            // current config settings
            var config = this._configSettings[this._currentConfigSetting];
            this.ActiveConfigSetting = config;

            // Defect 10030/10071 - prevent FFX lockup with ESX3 + HTTP(S) tunnel
            if(browsercaps.isMoz){
                if(config.TermClientType == TermClientType.Esx3Console && 
                    (config.TunnelConfigType == TunnelConfigType.HTTPTunnel ||
                     config.TunnelConfigType == TunnelConfigType.HTTPSTunnel)){
                    // raise the ultimate onconnect failure event   
                    log.error("[" + this.Id + "]:  URACoordinator stopped connection attempts on Firefox + ESX3Console + HTTP/HTTPS Tunneling.  (See defects 10030,10071.)");
                    alert('Console access to ESX3 virtual machines cannot be tunneled over HTTP(S) in Firefox browsers.\nPlease use Internet Explorer or change desktop connection type.');
                    // nullify the ActiveConfigSetting
                    this.ActiveConfigSetting = null;
                    // set the state to Disconnected
                    this.ConnectionState = URAConnectionStates.Disconnected;
                    // there are no more configuration settings to try so message a connect failure event to explain
                    // that all potential config settings have been attempted
                    this._raiseEvent("OnConnectFailure", null);
                    this.ConnectErrorOccurred = false;
                    this.LoadErrorOccurred = false;
                    return;
                }
            }

            // get the host address and port from the config setting
            this._hostAddress = config.HostAddress;
            this._hostPort = config.HostPort;

            // instantiate the TermClient control and bind its events
            this.ActiveTermClient = termClientFactory.getTermClient(this.Id + "_" + this._currentConfigSetting + "_tc", config.TermClientType, config.ControlPlatform);
            this.ActiveTermClient.OnConnect = this._getHandler("termClientConnectHandler");
            this.ActiveTermClient.OnDisconnect = this._getHandler("termClientDisconnectHandler");
            this.ActiveTermClient.OnConnectError = this._getHandler("termClientConnectErrorHandler");
            this.ActiveTermClient.OnLoadError = this._getHandler("termClientLoadErrorHandler");
            this.ActiveTermClient.OnAutoReconnecting = this._getHandler("termClientAutoReconnectingHandler");
            this.ActiveTermClient.OnCancelInterval = this._getHandler("termClientCancelIntervalHandler");
            log.info("[" + this.Id + "]:  URACoordinator created new " + this.ActiveTermClient.getClass());

            // instantiate the TunnelConfig control and bind its events
            this.ActiveTunnelConfig = tunnelConfigFactory.getTunnelConfig(this.Id + "_" + this._currentConfigSetting + "_tnl", config.TunnelConfigType, config.ControlPlatform);
            this.ActiveTunnelConfig.OnConnect = this._getHandler("tunnelConfigConnectHandler");
            this.ActiveTunnelConfig.OnDisconnect = this._getHandler("tunnelConfigDisconnectHandler");
            this.ActiveTunnelConfig.OnConnectError = this._getHandler("tunnelConfigConnectErrorHandler");
            this.ActiveTunnelConfig.OnLoadError = this._getHandler("tunnelConfigLoadErrorHandler");
            log.info("[" + this.Id + "]:  URACoordinator created new " + this.ActiveTunnelConfig.getClass());

            // set the connection properties on the TunnelConfig
            log.info("[" + this.Id + "]:  URACoordinator initializing the TunnelConfig and TermClient");
            this.ActiveTunnelConfig.GatewayAddress = this._gatewayAddress;
            this.ActiveTunnelConfig.HostAddress = this._hostAddress;
            this.ActiveTunnelConfig.HostPort = this._hostPort;
            if(this._gatewayPort != ""){
                this.ActiveTunnelConfig.GatewayPort = this._gatewayPort;
            }
            this.ActiveTunnelConfig.HostProtocol = this.ActiveTermClient.Protocol;

            // attempt to write the IFrame's document, then wait until it registers the onload event
            // before writing in any of the TermClient or TunnelConfig html
            this._writeHtml();
        }
        catch (e)
        {
            log.fatal("[" + this.Id + "]:  URACoordinator sufferred a fatal error during the connect() method: " + e.message);
        }
    }

    /// <summary>
    /// Cancels the current connection attempt cycle and suppresses any eventing from the control.
    /// This method wipes out any ActiveX or Applet controls that have started to load in the page.
    /// </summary>
    this.cancelConnect = _cancelConnect;
    function _cancelConnect(){
        log.info("[" + this.Id + "]:  URACoordinator received cancelConnect() call.");
        if(this.ConnectionState == URAConnectionStates.Connecting){
            log.info("[" + this.Id + "]:  URACoordinator cancelling connection attempt.");
            this._cancelInterval();
            this._cancelTimeout();
            if(this.ActiveTermClient != null){
                // disconnect any event handlers for the current TermClient
                this.ActiveTermClient.OnConnect = null;
                this.ActiveTermClient.OnDisconnect = null;
                this.ActiveTermClient.OnConnectError = null;
                this.ActiveTermClient.OnLoadError = null;
                this.ActiveTermClient.OnAutoReconnecting = null;
                this.ActiveTermClient.OnCancelInterval = null;
                this.ActiveTermClient._cancelTimeout();
                // nullify the current TermClient
                this.ActiveTermClient = null;
            }

            if(this.ActiveTunnelConfig != null){
                // disconnect any event handlers for the current TunnelConfig
                this.ActiveTunnelConfig.OnConnect = null;
                this.ActiveTunnelConfig.OnDisconnect = null;
                this.ActiveTunnelConfig.OnConnectError = null;
                this.ActiveTunnelConfig.OnLoadError = null;
                this.ActiveTunnelConfig._cancelTimeout();
                // nullify the current TunnelConfig
                this.ActiveTunnelConfig = null;
            }

            try
            {
                // try to remove any applets or activex controls from the page
                this._termClientTarget = this.TargetFrame.document.getElementById(this._termClientTargetId);
                this._termClientTarget.innerHtml = "";
                this._tunnelConfigTarget = this.TargetFrame.document.getElementById(this._tunnelConfigTargetId);
                this._tunnelConfigTarget.innerHtml = "";
            }
            catch (e)
            { 
                // swallow the error
            }
        }
    }

    /// <summary>
    /// Immediately aborts all TermClient and TunnelConfigs and stops communication between 
    /// controls.
    /// </summary>
    this.abort = _abort;
    function _abort(){
        log.info("[" + this.Id + "]:  URACoordinator received abort() call.");
        if(this.ConnectionState == URAConnectionStates.Connected){
            log.info("[" + this.Id + "]:  URACoordinator aborting connection.");
            this._cancelTimeout();
            // call the disconnect methods on the ActiveTermClient, once it has successfully 
            // disconnected it the DisconnectHandler for the TermClient will call the 
            // TunnelConfig's disconnect() method in turn.
            this.ActiveTermClient.disconnect();
        }
    }

    /// <summary>
    /// Sends the Ctrl-Alt-Delete command to the active TermClient.
    /// </summary>
    this.sendCtrlAltDelete = _sendCtrlAltDelete;
    function _sendCtrlAltDelete(){
        if(this.ActiveTermClient != null){
            this.ActiveTermClient.sendCtrlAltDelete();
        }
    }

    /// <summary>
    /// Method to retrieve the key commands to send Ctrl+Alt+Delete to the TermClient control.
    /// </summary>
    this.getCADCommand = _getCADCommand;
    function _getCADCommand(){
        return this.ActiveTermClient.getCADCommand();
    }

    /// <summary>
    /// Method handles the browser differences to write the html to the appropriate target.
    /// </summary>
    this._writeHtml = _writeHtml;
    function _writeHtml(){
        log.info("[" + this.Id + "]:  URACoordinator attempting to writing HTML to target IFrame.");
        try{
            if( browsercaps.isMoz ){
                this.TargetFrame.document.open();
                this.TargetFrame.document.write(this.getHtml());
                this.TargetFrame.document.close();
            } else {
                this.TargetFrame.location = "javascript:parent." + this.Id + ".getHtml();";
            }
        } catch (e) {
            log.error("[" + this.Id + "]:  URACoordinator sufferred a fatal error during the _writeHtml method: " + e.message);
        }
    }

    /// <summary>
    /// Method returns the HTML needed to render the document contents of the target 
    /// IFrame.  This document includes a callback function that notifies the URACoordinator 
    /// that the document has been loaded and is ready for further DOM injection.
    /// </summary>
    this.getHtml = _getHtml;
    function _getHtml(){
    return '<html><head><title>Surgient URA Window</title>' +
        '<script language="javascript">' +
        'function callback(){' +
        'parent.' + this.Id + '.pageReadyHandler();' +
        '}' +
        '</script>' +
        '<style>' + 
        'body{margin:0px;padding:0px;background-color:#FFFFFF;} ' + 
        'h3{color:#565656;font-family:Arial,Sans-Serif;font-size:11px;font-weight:bold;} ' +
        'p{color:#565656;font-family:Arial,Sans-Serif;font-size:11px;font-weight:normal;} ' +
        'a{color:#3D70B8;cursor:pointer;font-size:11px;font-family:Arial,Sans-Serif;font-weight:bold;text-decoration:none;} ' +
        'a:hover{text-decoration:underline;} ' +
        '.bd{background-color:#FFFFFF;text-align:center;}' + 
        '.tc{background-color:#FFFFFF;text-align:center;} ' + 
        '</style></head><body onload="callback();"><div class="bd">' +
        '<div id="' + this._termClientTargetId + '" class="tc"></div>' +
        '<div id="' + this._tunnelConfigTargetId + '" style="position:absolute;top=0;left=-100;width:2px;"></div>' +
        '</div></body></html>';
    }

    /// <summary>
    /// Method called by the target IFrame's document when the page has finished 
    /// loading indicating that it is ready for the URACoordinator to inject 
    /// the HTML needed for the TunnelConfig and TermClient into the appropriate 
    /// locations.
    /// </summary>
    this.pageReadyHandler = _pageReadyHandler;
    function _pageReadyHandler(){
        // get the div elements inside of the IFrame
        this._termClientTarget = this.TargetFrame.document.getElementById(this._termClientTargetId);
        this._tunnelConfigTarget = this.TargetFrame.document.getElementById(this._tunnelConfigTargetId);
        // pass the HTML elements into the TunnelConfig and TermClient
        this.ActiveTunnelConfig.Element = this.TargetFrame.document;
        this.ActiveTermClient.Element = this.TargetFrame.document;

        // write the tunnelConfig html to the iframe element, 
        // then wait until the 
        var srcHtml = this.ActiveTunnelConfig.renderHtml();
        this._tunnelConfigTarget.innerHTML = srcHtml;
        log.debug("[" + this.Id + "]:  URACoordinator rendered " + this.ActiveTunnelConfig.getClass() + ".html = \r\n" + srcHtml);
        log.info("[" + this.Id + "]:  URACoordinator successfully rendered TunnelConfig type: " + this.ActiveTunnelConfig.getClass() + " to page.");
        
        // initialize the TunnelConfig, once this has been initialized URACoordinator will
        // attempt to initialize the TermClient
        this._setTimeout(this.Id + "._initTunnelConfig()", 500);
    }

    /// <summary>
    /// Private method that is called after a fixed interval unless the URACoordinator receives an OnConnect or 
    /// OnConnectError event from the TermClient.  This is to fix an Win SP1 bug where ActiveX control event 
    /// wireup does not happen automatically after the control is initially downloaded.
    /// </summary>
    this._failSafeLoadHandler = _failSafeLoadHandler;
    function _failSafeLoadHandler(){
        // no activity was registered by the TermClient control so we can assume that there was a connectError event
        this._cancelInterval();
        log.info("[" + this.Id + "]:  URACoordinator failed to receive a timely OnConnect event from " + this.ActiveTermClient.getClass() + 
            " forcing OnConnectError event for the TermClient");
        this.termClientConnectErrorHandler();
    }

    /// <summary>
    /// Private method to handle the initialization of the TunnelConfig.
    /// </summary>
    this._initTunnelConfig = _initTunnelConfig;
    function _initTunnelConfig(){
        try{
            log.info("[" + this.Id + "]:  URACoordinator calling TunnelConfig.connect()");
            this.ActiveTunnelConfig.connect();
        } catch (e){
            log.error("[" + this.Id + "]:  URACoordinator could not call TunnelConfig.connect() due to error: " + e.message);
            this.ConnectErrorOccurred = true;
            this._raiseEvent("OnConnectError", null);
        }
    }
    
    /// <summary>
    /// Private method to handle the initialization of the TermClient.
    /// </summary>
    this._initTermClient = _initTermClient;
    function _initTermClient(){
        try{
            this.ActiveTermClient.HostAddress = this.ActiveTunnelConfig.getDestinationIPAddress();
            this.ActiveTermClient.HostPort = this.ActiveTunnelConfig.getDestinationPort();
            this.ActiveTermClient.Width = this._getTargetWidth();
            this.ActiveTermClient.Height = this._getTargetHeight();
            this.ActiveTermClient.Username = this.Username;
            this.ActiveTermClient.Password = this.Password;
            this.ActiveTermClient.ProtocolUsername = this.ProtocolUsername;
            this.ActiveTermClient.ProtocolPassword = this.ProtocolPassword;
            this.ActiveTermClient.VmName = this.VmName;
            this.ActiveTermClient.VmFile = this.VmFile;
            this.ActiveTermClient.HostUsername = this.HostUsername;
            this.ActiveTermClient.HostPassword = this.HostPassword;
            this.ActiveTermClient.HostType = this.HostType;
            this.ActiveTermClient.HostVersion = this.HostVersion;
            var inited = this.ActiveTermClient.init();
            if ((inited == false) || (inited == "abort")){
                log.info("[" + this.Id + "]:  URACoordinator received OnLoadError event from " + this.ActiveTermClient.getClass());
                this.LoadErrorOccurred = true;
                // inited is a short cut for TermClients that suffer load errors during the init method
                this._raiseEvent("OnLoadError", "TermClient OnLoadError event.");  
                // short-circuit cycling the config settings if abort was passed back...
                if (inited == "abort"){
                    this._currentConfigSetting = this._configSettings.length - 1;
                }
                // give the Applet/ActiveX control time to close the event callstack before removing it
                this._setTimeout(this.Id + "._cycleConfigSetting(true)", 500);                
                return;
            }
            log.info("[" + this.Id + "]:  URACoordinator set TermClient HostAddress: " + this.ActiveTermClient.HostAddress + 
                " and HostPort: " + this.ActiveTermClient.HostPort);

            // generate the HTML for the TermClient and write it into the document
            var srcHtml = this.ActiveTermClient.renderHtml();
            this._termClientTarget.innerHTML = srcHtml;
            log.debug("[" + this.Id + "]:  URACoordinator rendered " + this.ActiveTermClient.getClass() + ".html = \r\n" + srcHtml);
            log.info("[" + this.Id + "]:  URACoordinator successfully rendered TermClient type: " + this.ActiveTermClient.getClass() + " to page.");

            this._setTimeout(this.Id + "._connectTermClient()", 1000);
        } catch (e){
            log.error("[" + this.Id + "]:  URACoordinator could not render TermClient due to error: " + e.message);
            this.ConnectErrorOccurred = true;
            this._raiseEvent("OnConnectError", null);
        }
    }

    /// <summary>
    /// Private method that tries to make the ActiveTermClient control connect.
    /// </summary>
    this._connectTermClient = _connectTermClient;
    function _connectTermClient(){
        log.debug("[" + this.Id + "]:  Enter URACoordinator._connectTermClient");
        try{
            log.info("[" + this.Id + "]:  URACoordinator calling TermClient.connect()");
            this._setInterval(this.Id + "._failSafeLoadHandler()", this._loadFailSafe);
            this.ActiveTermClient.connect();
        } catch (e){
            log.error("[" + this.Id + "]:  URACoordinator could not call TunnelConfig.connect() due to error: " + e.message);
            this.ConnectErrorOccurred = true;
            this._raiseEvent("OnConnectError", null);
        }
    }

    /// <summary>
    /// Private method that tries to cycle to the next URAConfigSetting to see if a valid connection
    /// can still be made, if not it raises the OnConnectError
    /// </summary>
    /// <param type="bool" name="bSkip">if true, the function cycles until a change in control platform
    /// is found, if false it will continue to the next control setting in the list</param>
    this._cycleConfigSetting = _cycleConfigSetting;
    function _cycleConfigSetting(bSkip){
        // if skip is true, cycle through until the ControlPlatform has changed because the current ControlPlatform
        // appears to be blocked by the browser or user.  If another ControlPlatform is not available, raise the 
        // OnLoadFailure event to separate it from any connection failures
        if(bSkip){
            log.debug("[" + this.Id + "]:  URACoordinator control load failed, cycling to next ControlPlatform.");
            var activeSetting = this._configSettings[this._currentConfigSetting];
            // cycle through the config settings until the ControlPlatform changes
            while(activeSetting.ControlPlatform == this._configSettings[this._currentConfigSetting].ControlPlatform){
                if(this._currentConfigSetting < this._configSettings.length - 1){
                    this._currentConfigSetting++;
                } else {
                    log.error("[" + this.Id + "]:  URACoordinator failed to load any URAConfigSettings successfully.");
                    // nullify the ActiveConfigSetting
                    this.ActiveConfigSetting = null;
                    // set the state to Disconnected
                    this.ConnectionState = URAConnectionStates.Disconnected;
                    // based on whether or not an OnConnectError event occurred, messate an OnConnectFailure event 
                    // or an OnLoadFailure event
                    if(this.ConnectErrorOccurred){
                        
                        // there are no more configuration settings to try so message a connect failure event to explain
                        // that all potential config settings have been attempted
                        this._raiseEvent("OnConnectFailure", null);
                    } else {
                        // there are no more configuration settings to try so message a connect failure event to explain
                        // that all potential config settings have been attempted
                        this._raiseEvent("OnLoadFailure", null);
                    }
                    this.ConnectErrorOccurred = false;
                    this.LoadErrorOccurred = false;
                    return;
                }
            }
        } else {
            this._currentConfigSetting++;
        }

        if(this._currentConfigSetting < this._configSettings.length){
            log.debug("[" + this.Id + "]:  URACoordinator connection failed, now attempting URAConfigSetting: " + this._currentConfigSetting);
            // force abort any controls and remove the references to the Javascript Objects after 
            // connect error to prevent any additional callbacks from breaking the thread
            this._tunnelConfigTarget.innerHTML = "";
            this._termClientTarget.innerHTML = "";
            this.ActiveTermClient = null;
            this.ActiveTunnelConfig = null;
            this.init(this.Username, this.Password, this._gatewayAddress, this._gatewayPort,
                this.ProtocolUsername, this.ProtocolPassword, this.VmName, this.VmFile, 
                this.HostUsername, this.HostPassword, this.HostType, this.HostVersion);
            this.connect();
        } else {
            log.error("[" + this.Id + "]:  URACoordinator failed to connect any URAConfigSettings successfully.");
            // nullify the ActiveConfigSetting
            //this.ActiveConfigSetting = null;
            // set the state to ConnectError
            this.ConnectionState = URAConnectionStates.ConnectionError;
            // there are no more configuration settings to try so message a connect failure event to explain
            // that all potential config settings have been attempted
            this._raiseEvent("OnConnectFailure", null);
            this.ConnectErrorOccurred = false;
            this.LoadErrorOccurred = false;
        }
    }

/// region : Event Delegates ----------------------------------------
    /// <summary>
    /// Event delegate for the Connect event.
    /// </summary>
    this.OnConnect = null;

    /// <summary>
    /// Event delegate for the ConnectError event.  This event is raised
    /// any time a TermClient or TunnelConfig fail to connect.
    /// </summary>
    this.OnConnectError = null;

    /// <summary>
    /// Event delegate for the Disconnect event.
    /// </summary>
    this.OnDisconnect = null;

    /// <summary>
    /// Event delegate for the LoadError event.
    /// </summary>
    this.OnLoadError = null;

    /// <summary>
    /// Event delegate for the ConnectFailure event.  This event is raised 
    /// when all the connection configurations have been attempted and failed.
    /// </summary>
    this.OnConnectFailure = null;

    /// <summary>
    /// Event delegate for the LoadFailure event.  This event is raised 
    /// when all the connection configurations have been attempted and
    /// all ControlPlatforms failed to load controls.
    /// </summary>
    this.OnLoadFailure = null;
    
    /// <summary>
    /// Event delegate for the AutoReconnecting event.  This event is raised 
    /// when the terminal client's control automatically attempts to reconnect
    /// after a disconnect. (currently only RDP ActiveX supports this)
    /// </summary>
    this.OnAutoReconnecting = null;   

/// region : Event Handlers -----------------------------------------    
    /// <summary>
    /// Event handler for the TunnelConfig Connect event.
    /// </summary>
    /// <param name="sender" type="object">object raising the event</param>
    /// <param name="args" type="object">any event arguments</param>
    this.tunnelConfigConnectHandler = _tunnelConfigConnectHandler;
    function _tunnelConfigConnectHandler(sender, args){
        log.info("[" + this.Id + "]:  URACoordinator received OnConnect event from " + this.ActiveTunnelConfig.getClass());
        // if the TunnelConfig connected safely then try to initialize and connect the TermClient
        this._initTermClient();
    }

    /// <summary>
    /// Event handler for the TunnelConfig Disconnect event.
    /// </summary>
    /// <param name="sender" type="object">object raising the event</param>
    /// <param name="args" type="object">any event arguments</param>
    this.tunnelConfigDisconnectHandler = _tunnelConfigDisconnectHandler;
    function _tunnelConfigDisconnectHandler(sender, args){
        log.info("[" + this.Id + "]:  URACoordinator received OnDisconnect event from " + this.ActiveTunnelConfig.getClass());
        // the TermClient disconnect takes precedence over the TunnelConfig 
        // on the OnDisconnect event, so only allow that control's 
        // disconnection to trigger raising the event
    }

    /// <summary>
    /// Event handler for the TunnelConfig ConnectError event.
    /// </summary>
    /// <param name="sender" type="object">object raising the event</param>
    /// <param name="args" type="object">any event arguments</param>
    this.tunnelConfigConnectErrorHandler = _tunnelConfigConnectErrorHandler;
    function _tunnelConfigConnectErrorHandler(sender, args){
        // if the TunnelConfig did not connect, then cycle to the next TunnelConfig
        // available in the system and try to connect on that.
        log.info("[" + this.Id + "]:  URACoordinator received OnConnectError event from " + this.ActiveTunnelConfig.getClass());
        this.ConnectErrorOccurred = true;
        // raise the ConnectError event
        this._raiseEvent("OnConnectError", "TunnelConfig");
        // give the Applet/ActiveX control time to close the event callstack before removing it
        this._setTimeout(this.Id + "._cycleConfigSetting(false)", 500);
    }

    /// <summary>
    /// Event handler for the TunnelConfig LoadError event.
    /// </summary>
    /// <param name="sender" type="object">object raising the event</param>
    /// <param name="args" type="object">any event arguments</param>
    this.tunnelConfigLoadErrorHandler = _tunnelConfigLoadErrorHandler;
    function _tunnelConfigLoadErrorHandler(sender, args){
        log.info("[" + this.Id + "]:  URACoordinator received OnLoadError event from " + this.ActiveTunnelConfig.getClass());
        this.LoadErrorOccurred = true;
        // we have no way of handling the inability to load the TunnelConfig
        // control through the URA framework so just message up an OnLoadError
        // event and let the hosting page handle the situation
        this._raiseEvent("OnLoadError", "TunnelConfig OnLoadError event.");
        // give the Applet/ActiveX control time to close the event callstack before removing it
        this._setTimeout(this.Id + "._cycleConfigSetting(true)", 500);
    }

    /// <summary>
    /// Event handler for the TermClient Connect event.
    /// </summary>
    /// <param name="sender" type="object">object raising the event</param>
    /// <param name="args" type="object">any event arguments</param>
    this.termClientConnectHandler = _termClientConnectHandler;
    function _termClientConnectHandler(sender, args) {
        log.info("[" + this.Id + "]:  URACoordinator received OnConnect event from " + this.ActiveTermClient.getClass()); 
        // set the internal state
        this.ConnectionState = URAConnectionStates.Connected;
        this._cancelInterval();
        // raise the OnConnect event up to any listeners
        this._raiseEvent("OnConnect", "TermClient");
    }

    /// <summary>
    /// Event handler for the TermClient Disconnect event.
    /// </summary>
    /// <param name="sender" type="object">object raising the event</param>
    /// <param name="args" type="object">any event arguments</param>
    this.termClientDisconnectHandler = _termClientDisconnectHandler;
    function _termClientDisconnectHandler(sender, args){
        log.info("[" + this.Id + "]:  URACoordinator received OnDisconnect event from " + this.ActiveTermClient.getClass()); 
        // try to disconnect the ActiveTunnelConfig control
        try {
            log.info("[" + this.Id + "]:  URACoordinator attempting to disconnect TunnelConfig: " + this.ActiveTunnelConfig.getClass());
            this.ActiveTunnelConfig.disconnect();
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  URACoordinator failed to disconnect TunnelConfig: " + this.ActiveTunnelConfig.getClass() + " with error: " + e.message);
        }
        // set the connection state to disconnected
        this.ConnectionState = URAConnectionStates.Disconnected;

        // raise the OnDisconnect event up to any listeners
        var argsOut = (args != null) ? args : "TermClient";
        this._raiseEvent("OnDisconnect", argsOut);
    }

    /// <summary>
    /// Event handler for the TermClient ConnectError event.
    /// </summary>
    /// <param name="sender" type="object">object raising the event</param>
    /// <param name="args" type="TermClientConnectErrorArgs">specific action to take, may be null</param>
    this.termClientConnectErrorHandler = _termClientConnectErrorHandler;
    function _termClientConnectErrorHandler(sender, args){
        log.info("[" + this.Id + "]:  URACoordinator received OnConnectError event from " + this.ActiveTermClient.getClass() + ", args=" + args);
        this._cancelInterval();
        // Check what to do next
        switch(args){
            case TermClientConnectErrorArgs.Abort:
                // TermClient indicates not to try the next TermClient
                // set the state to ConnectError and raise ConnectFailure
                this.ActiveConfigSetting = null;
                this.ConnectionState = URAConnectionStates.ConnectionError;
                this._raiseEvent("OnConnectFailure", null);
                this.ConnectErrorOccurred = false;
                this.LoadErrorOccurred = false;
                break;
            default:
                // raise the ConnectError event and try next
                this.ConnectErrorOccurred = true;
                this._raiseEvent("OnConnectError", "TermClient");
                this._setTimeout(this.Id + "._cycleConfigSetting(false)", 500);
        }
    }

    /// <summary>
    /// Event handler for the TermClient LoadError event.
    /// </summary>
    /// <param name="sender" type="object">object raising the event</param>
    /// <param name="args" type="object">any event arguments</param>
    this.termClientLoadErrorHandler = _termClientLoadErrorHandler;
    function _termClientLoadErrorHandler(sender, args){
        log.info("[" + this.Id + "]:  URACoordinator received OnLoadError event from " + this.ActiveTermClient.getClass()); 
        this.LoadErrorOccurred = true;
        this._cancelInterval();
        // we have no way of handling the inability to load the TermClient
        // control through the URA framework so just message up an OnLoadError
        // event and let the hosting page handle the situation
        this._raiseEvent("OnLoadError", "TermClient OnLoadError event.");
        // give the Applet/ActiveX control time to close the event callstack before removing it
        this._setTimeout(this.Id + "._cycleConfigSetting(true)", 500);
    }

    /// <summary>
    /// Event handler for the TermClient AutoReconnecting event.
    /// </summary>
    /// <param name="sender" type="object">object raising the event</param>
    /// <param name="args" type="object">any event arguments</param>
    this.termClientAutoReconnectingHandler = _termClientAutoReconnectingHandler;
    function _termClientAutoReconnectingHandler(sender, args){
        log.info("[" + this.Id + "]:  URACoordinator received OnAutoReconnecting event from " + this.ActiveTermClient.getClass()); 
        // pass the event up to the hosting page
        this._raiseEvent("OnAutoReconnecting", "TermClient OnAutoReconnecting event.");
    }

    /// <summary>
    /// Event handler for the TermClient CancelInterval event.
    /// </summary>
    /// <param name="sender" type="object">object raising the event</param>
    /// <param name="args" type="object">any event arguments</param>
    this.termClientCancelIntervalHandler = _termClientCancelIntervalHandler;
    function _termClientCancelIntervalHandler(sender, args){
        log.info("[" + this.Id + "]:  URACoordinator received OnCancelInterval event from " + this.ActiveTermClient.getClass()); 
        this._cancelInterval();
    }
}


/**********************************************************************
   $Author: csanford $
   $Date: 2008/04/03 19:47:29 $
   $Revision: 1.25 $


   Copyright 2001 - 2004. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/

/// <summary>
/// Implementation class for the Citrix ActiveX TermClient object.
/// </summary>
/// <param name="id" type="string">the id of the TermClient instance</param>
function CitrixActiveXTermClient(id){
/// region : inheritance --------------------------------------------
    this.base = TermClient;
    this.base(id);
    log.info("[" + id + "]:  CitrixActiveXTermClient object created.");

/// region : private fields -----------------------------------------
    this._ctlSuffix = "_ax";

/// region : private fields -----------------------------------------
    this._termClientType = TermClientType.Citrix;
    this._control = null; // holds a reference to the HTML element
    this._connectCount = 25; // counter for the number of permissable connection attempts
    this._downloadCount = 45; // counter for the number of attempts tried before the download is considered failure

/// region : Properties ---------------------------------------------

    /// <summary>
    /// Gets/sets the Protocol for this object.
    /// </summary>
    this.Protocol = TermClientProtocol.Citrix;

    /// <summary>
    /// Gets/sets the ControlPlatform for this object.
    /// </summary>
    this.Platform = ControlPlatform.ActiveX;

    /// <summary>
    /// Gets/sets the TermClientType for this object.
    /// </summary>
    this.TermClientType = TermClientType.Citrix;

    /// <summary>
    /// Gets/sets the control's ScalingMode property.  See control ScalingMode docs.
    /// </summary>
    this.ScalingMode = 3;

    /// <summary>
    /// Gets/sets the control's Desired color depth property.  See control DesiredColor docs.
    /// </summary>
    this.DesiredColor = 16;

/// region : Methods ------------------------------------------------

    /// <summary>
    /// Method handles any initialization needed for the control before the connect() method 
    /// is called.  Not all controls will implement the init() method therefore this is not 
    /// a "virtual" method, just an empty stub that must be overridden for any effect to occur.
    /// </summary>
    /// <param name="args" type="object">initialization arguments, this is dependent upon implementation</param>
    this.init = _init;
    function _init(args){
        // no noop call here, if a control does not override, fail silently.
        return;
    }

    /// <summary>
    /// Method tells the TermClient to attempt to start the remote session. Raises 
    /// an OnConnect event.
    /// </summary>
    this.connect = _connect;
    function _connect(){        
        // create a counter for the number of connection attempts
        if(typeof(this._connectionAttempt) == "undefined"){
            this._connectionAttempt = 0;
        }
        try
        {
            // find our control and bind to it
            this._control = this.Element.getElementById(this.Id + this._ctlSuffix);
            if(this._control == null){
                log.error("[" + this.Id + "]:  CitrixActiveXTermClient unable to find rendered object tag in document.");
                throw this._newError("No download error.");
            }
            log.debug("[" + this.Id + "]:  CitrixActiveXTermClient._control = " + this._control);
            if(this._control == null || typeof(this._control.Connect) == "undefined"){
                log.info("[" + this.Id + "]:  CitrixActiveXTermClient attempting connection:  " + this._connectionAttempt);
                if(this._connectionAttempt < this._downloadCount){
                    this._connectionAttempt++;
                    this._setTimeout(this.Id + ".connect()", 1000);
                } else {
                    this._raiseEvent("OnLoadError", null);
                }
            } else {
                log.info("[" + this.Id + "]:  CitrixActiveXTermClient preparing to connect.");
                this._control.Address = this.HostAddress + ":" + this.HostPort;
                this._hostURL = this.Protocol + "://" + this.HostAddress + ":" + this.HostPort;
                // set the username & password
                this._control.SetProp("Username", this.Username);
                this._control.SetProp("Password", this.Password);
                this._control.SetProp("CDMAllowed", false);
                // set the global config settings
                var colorDepth;
                switch(TerminalClientSettings.ColorDepth){
                    case 8 : 
                        colorDepth = 2;
                        break;
                    case 16 : 
                        colorDepth = 4;
                        break;
                    case 24 :
                        colorDepth = 8;
                        break;
                    case 32 : 
                        colorDepth = 16;
                        break;
                    default : 
                        colorDepth = 8;
                }
                this._control.SetProp("DesiredColor", colorDepth);
                this._control.SetProp("ClientAudio", TerminalClientSettings.EnableSound);
                //this._control.SetProp("", TerminalClientSettings.EnableFullScreen); // not supported
                this._control.SetProp("CDMAllowed", TerminalClientSettings.EnableDriveMapping);
                // connect the control
                this._control.Connect();
                this._control.ScalePercent(100);
            }
        }
        catch (e)
        {
            if(e.message == "No download error."){
                log.fatal("[" + this.Id + "]:  CitrixActiveXTermClient control unable to initialize due to download or installation error.");
            } else {
                log.fatal("[" + this.Id + "]:  CitrixActiveXTermClient control suffered a fatal initialization error: " + e.message);
            }
            this._raiseEvent("OnConnectError", null);
        }
    }

    /// <summary>
    /// Method tells the TermClient to attempt to disconnect from the remote session.
    /// </summary>
    this.disconnect = _disconnect;
    function _disconnect(args) {
        try{
            this._control.Disconnect();
            log.info("[" + this.Id + "]:  CitrixActiveXTermClient successfully disconnected from: " + this._hostURL);
        } catch (e){
            log.error("[" + this.Id + "]:  CitrixActiveXTermClient suffered an error attempting to disconnect: " + e.message);
        }
    }

    /// <summary>
    /// Method renders the TermClient's HTML to the target frame's document.  The method 
    /// of render varies for each implementation.
    /// </summary>
    this.renderHtml = _renderHtml;
    function _renderHtml() {
        var ctlid = this.Id + this._ctlSuffix;
        return '<object id="' + ctlid + '"' + 
                    'classid="CLSID:238F6F83-B8B4-11CF-8771-00A024541EE3"' + 
                    'codebase="' + appPath + '/URA/lib/swficat.cab#version=10,200,2650,0"' + 
                    'width="' + this.Width + '" height="' + this.Height + '"' + 
                    'style="position:absolute;top:0px;left:0px;padding:0px;margin:0px;" >' + 
                    '<param name="Start" value="False" />' + 
                    '<param name="Border" value="0" />' + 
                    '<param name="DesiredHRes" value="' + this.Width + '" />' + 
                    '<param name="DesiredVRes" value="' + this.Height + '" />' + 
                    '<param name="DesiredColor" value="' + this.DesiredColor + '" />' + 
                    '<param name="ScalingMode" value="' + this.ScalingMode + '" />' + 
                '</object>' + 
                '<SCRIPT language="javascript" for="' + ctlid + '" event="OnConnect()" type="text/javascript">' + 
                'parent.' + this.Id + '.controlConnectHandler();</SCRIPT>' + 
                '<SCRIPT language="javascript" for="' + ctlid + '" event="OnDisconnect()" type="text/javascript">' + 
                'parent.' + this.Id + '.controlDisconnectHandler();</SCRIPT>' + 
                '<SCRIPT language="javascript" for="' + ctlid + '" event="OnConnectFailed()" type="text/javascript">' + 
                'parent.' + this.Id + '.controlConnectErrorHandler();' + 
                '</SCRIPT>';
    }

    /// <summary>
    /// Method to send Ctrl+Alt+Delete to the TermClient control
    /// </summary>
    this.sendCtrlAltDelete = _sendCtrlAltDelete;
    function _sendCtrlAltDelete(){
        alert('To send Ctrl+Alt+Delete use the following key combination:\n\tCTRL + F1');
    }

    /// <summary>
    /// Method to retrieve the key commands to send Ctrl+Alt+Delete to the TermClient control.
    /// </summary>
    this.getCADCommand = _getCADCommand;
    function _getCADCommand(){
        return "CTRL + F1";
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnConnect event.
    /// </summary>
    this.controlConnectHandler = _controlConnectHandler;
    function _controlConnectHandler(){
        log.info("[" + this.Id + "]:  CitrixActiveXTermClient received connect event from the ActiveX control for: " + this._hostURL);
        // raise the OnConnect event
        this._raiseEvent("OnConnect", null);
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnDisconnect event.
    /// </summary>
    this.controlDisconnectHandler = _controlDisconnectHandler;
    function _controlDisconnectHandler(){
        log.info("[" + this.Id + "]:  CitrixActiveXTermClient received disconnect event from the ActiveX control for: " + this._hostURL);
        // raise the OnDisconnect event
        this._raiseEvent("OnDisconnect", null);
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnConnectError event.
    /// </summary>
    this.controlConnectErrorHandler = _controlConnectErrorHandler;
    function _controlConnectErrorHandler(){
        log.info("[" + this.Id + "]:  CitrixActiveXTermClient received connect error event from the ActiveX control for: " + this._hostURL);
        // raise the OnConnectError event
        this._raiseEvent("OnConnectError", null);
    }

    /// <summary>
    /// Method gets the ActiveX or Applet control of the TermClient depending upon what 
    /// ControlPlatform has been deployed.
    /// </summary>
    /// <return type="object">the internal control, if this control has not been properly
    /// initialized this method ***can return null***</return>
    this.getControl = _getControl;
    function _getControl(){
        return this._control;
    }

    /// <summary>
    /// Method determines if the control is actually connected or not, helpful for polling 
    /// exercises and error checking in the URACoordinators.
    /// </summary>
    this.isConnected = _isConnected;
    function _isConnected(){
        if(typeof(this._control.IsConnected) != "undefined"){
            if(this._control.IsConnected()){
                log.info("[" + this.Id + "]:  CitrixActiveXTermClient.isConnected returned: true");
                return true;
            } else {
                log.info("[" + this.Id + "]:  CitrixActiveXTermClient.isConnected returned: false");
                return false;
            }
        } else {
            log.info("[" + this.Id + "]:  CitrixActiveXTermClient.isConnected returned: false");
            return false;
        }
    }
}
// register this instance with the TermClientFactory
termClientFactory.registerTermClient(ControlPlatform.ActiveX, TermClientType.Citrix, "CitrixActiveXTermClient");


/**********************************************************************
   $Author: greynold $
   $Date: 2007/06/13 15:13:41 $
   $Revision: 1.19 $


   Copyright 2001 - 2004. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/

/// <summary>
/// Implementation class for the Citrix ActiveX TermClient object.
/// </summary>
/// <param name="id" type="string">the id of the TermClient instance</param>
function CitrixJavaTermClient(id){
/// region : inheritance --------------------------------------------
    this.base = TermClient;
    this.base(id);
    log.info("[" + id + "]:  CitrixJavaTermClient object created.");

/// region : private fields -----------------------------------------
    this._ctlSuffix = "_ax";

/// region : private fields -----------------------------------------
    this._termClientType = TermClientType.Citrix;
    this._control = null; // holds a reference to the HTML element
    this._connectCount = 25; // counter for the number of permissable connection attempts

/// region : Properties ---------------------------------------------

    /// <summary>
    /// Gets/sets the Protocol for this object.
    /// </summary>
    this.Protocol = TermClientProtocol.Citrix;

    /// <summary>
    /// Gets/sets the ControlPlatform for this object.
    /// </summary>
    this.Platform = ControlPlatform.Applet;

    /// <summary>
    /// Gets/sets the TermClientType for this object.
    /// </summary>
    this.TermClientType = TermClientType.Citrix;

    /// <summary>
    /// Gets/sets the control's ScalingMode property.  See control ScalingMode docs.
    /// </summary>
    this.ScalingMode = 3;

/// region : Methods ------------------------------------------------

    /// <summary>
    /// Method handles any initialization needed for the control before the connect() method 
    /// is called.  Not all controls will implement the init() method therefore this is not 
    /// a "virtual" method, just an empty stub that must be overridden for any effect to occur.
    /// </summary>
    /// <param name="args" type="object">initialization arguments, this is dependent upon implementation</param>
    this.init = _init;
    function _init(args){
        // no noop call here, if a control does not override, fail silently.
        return;
    }

    /// <summary>
    /// Method tells the TermClient to attempt to start the remote session. Raises 
    /// an OnConnect event.
    /// </summary>
    this.connect = _connect;
    function _connect(){        
        // create a counter for the number of connection attempts
        if(typeof(this._connectionAttempt) == "undefined"){
            this._connectionAttempt = 0;
        }

        try
        {
            // find our control and bind to it
            this._control = this.Element.getElementById(this.Id + this._ctlSuffix);
            if(this._control == null){
                log.error("[" + this.Id + "]:  CitrixJavaTermClient unable to find rendered object tag in document.");
                throw this._newError("No download error.");
            }
            log.debug("[" + this.Id + "]:  CitrixJavaTermClient._control = " + this._control);

            try
            {
                // if the control is null, throw an error so that the function is re-called.
            	if(this._control == null){
                    throw this._newError("Control not loaded.");
                }

                // the isConnected method is a simple boolean test, the results of which don't matter 
                // at this point, to verify that the control has been loaded properly this method just 
                // needs to return a value and not throw an exception because the method is not supported.
                if(this._control.isConnected() || !this._control.isConnected()){
                    log.info("[" + this.Id + "]:  CitrixJavaTermClient preparing to connect.");
                    this._hostURL = this.Protocol + "://" + this.HostAddress + ":" + this.HostPort;
                    this._setTimeout(this.Id + "._verifyConnection()", 1000);
                }
            }
            catch (e)
            {
                log.info("[" + this.Id + "]:  CitrixJavaTermClient attempting connection:  " + this._connectionAttempt);
                if(this._connectionAttempt < this._connectCount){
                    this._connectionAttempt++;
                    this._setTimeout(this.Id + ".connect()", 1000);
                } else {
                    this._raiseEvent("OnLoadError", null);
                }
            }
        }
        catch (e)
        {
            if(e.message == "No download error."){
                log.fatal("[" + this.Id + "]:  CitrixJavaTermClient control unable to initialize due to download or installation error.");
            } else {
                log.fatal("[" + this.Id + "]:  CitrixJavaTermClient control suffered a fatal initialization error: " + e.message);
            }
            this._raiseEvent("OnConnectError", null);
        }
    }

    /// <summary>
    /// A polling method that will attempt to determine if the control has successfully 
    /// connected or not when the control does not support callback mechanisms for the connection event.
    /// </summary>
    this._verifyConnection = _verifyConnection;
    function _verifyConnection(){
        if(typeof(this._verifyConnectionAttempt) == "undefined"){
            this._verifyConnectionAttempt = 0;
        }
        if(this.isConnected()){
            // the control is connected so begin the connection polling process
            this._setTimeout(this.Id + "._pollConnection()", 1000);
            // fake that there was a control connection event by calling the handler
            this.controlConnectHandler();
        } else {
            // attempt to verify connection for only 15 seconds to race against Citrix modal "fail to connect" dialog
            if(this._verifyConnectionAttempt < 15){
                this._verifyConnectionAttempt++;
                log.info("[" + this.Id + "]:  CitrixJavaTermClient attempting connection verification:  " + this._verifyConnectionAttempt);
                this._setTimeout(this.Id + "._verifyConnection()", 1000);
            } else {
                // fake that there was a control connection error by calling the handler
                this.controlConnectErrorHandler();
            }
        }
    }

    /// <summary>
    /// Callback method that polls the IsConnected property of the control to determine if the 
    /// connection is still active.  If it is not, the OnDisconnect event is raised.
    /// </summary>
    this._pollConnection = _pollConnection;
    function _pollConnection(){
        if(this.isConnected()){
            this._setTimeout(this.Id + "._pollConnection()", 1000);
        } else {
            // fake that there was a control disconnection by calling the handler
            this.controlDisconnectHandler();
        }
    }

    /// <summary>
    /// Method tells the TermClient to attempt to disconnect from the remote session.
    /// </summary>
    this.disconnect = _disconnect;
    function _disconnect(args) {
        try{
            //this._control.Disconnect();
            this._cancelTimeout();
            // fake that there was a control disconnection by calling the handler
            this.controlDisconnectHandler();
            log.info("[" + this.Id + "]:  CitrixJavaTermClient successfully disconnected from: " + this._hostURL);
        } catch (e){
            log.error("[" + this.Id + "]:  CitrixJavaTermClient suffered an error attempting to disconnect: " + e.message);
        }
    }

    /// <summary>
    /// Method renders the TermClient's HTML to the target frame's document.  The method 
    /// of render varies for each implementation.
    /// </summary>
    this.renderHtml = _renderHtml;
    function _renderHtml() {
        var ctlid = this.Id + this._ctlSuffix;
        var clientAudio = (TerminalClientSettings.EnableSound)? "on" : "off";
        var colorDepth;
        switch(TerminalClientSettings.ColorDepth){
            case 8 : 
                colorDepth = 2;
                break;
            case 16 : 
                colorDepth = 4;
                break;
            case 24 :
                colorDepth = 8;
                break;
            case 32 : 
                colorDepth = 8;
                break;
            default : 
                colorDepth = 8;
        }
        return '<applet id="' + ctlid + '"' + 
                    'code="com.citrix.JICA.class" ' + 
                    'archive="' + appPath + '/URA/lib/JICA-coreN.jar, ' + appPath + '/URA/lib/JICA-audioN.jar"' + 
                    'width="' + this.Width + '" height="' + this.Height + '"' + 
                    'style="padding:0px;margin:0px;" >' + 
                    '<param name="cabbase" value="' + appPath + '/URA/lib/JICAEngM.cab">' + 
                    '<param name="Start" value="auto" />' + 
                    '<param name="Border" value="0" />' + 
                    '<param name="ShowStatusBar" value="no"/>' + 
                    '<param name="ShowSettingsButton" value="no"/>' + 
                    '<param name="End" value="manual"/>' + 
                    '<param name="DesiredHRes" value="' + this.Width + '" />' + 
                    '<param name="DesiredVRes" value="' + this.Height + '" />' + 
                    '<param name="Address" value="' + this.HostAddress + '" />' + 
                    '<param name="ICAPortNumber" value="' + this.HostPort + '" />' + 
                    '<param name="TCPBrowserAddress" value="' + this.HostAddress + '" />' + 
                    '<param name="Username" value="' + this.Username + '" />' + 
                    '<param name="Password" value="' + this.Password + '" />' + 
                    '<param name="DesiredColor" value="' + colorDepth + '" />' + 
                    '<param name="ClientAudio" value="' + clientAudio + '" />' + // accepted values on/off
                    //'<param name="CDMAllowed" value="' + TerminalClientSettings.EnableDriveMapping + '" />' + // not supported
                    //'<param name="" value="' + TerminalClientSettings.EnableFullScreen + '" />' + // not supported
                '</applet>';
    }

    /// <summary>
    /// Method to send Ctrl+Alt+Delete to the TermClient control
    /// </summary>
    this.sendCtrlAltDelete = _sendCtrlAltDelete;
    function _sendCtrlAltDelete(){
        alert('To send Ctrl+Alt+Delete use the following key combination:\n\tCTRL + F1');
    }

    /// <summary>
    /// Method to retrieve the key commands to send Ctrl+Alt+Delete to the TermClient control.
    /// </summary>
    this.getCADCommand = _getCADCommand;
    function _getCADCommand(){
        return "CTRL + F1";
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnConnect event.
    /// </summary>
    this.controlConnectHandler = _controlConnectHandler;
    function _controlConnectHandler(){
        log.info("[" + this.Id + "]:  CitrixJavaTermClient successfully connected to: " + this._hostURL);
        // raise the OnConnect event
        this._raiseEvent("OnConnect", null);
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnDisconnect event.
    /// </summary>
    this.controlDisconnectHandler = _controlDisconnectHandler;
    function _controlDisconnectHandler(){
        log.info("[" + this.Id + "]:  CitrixJavaTermClient successfully disconnected from: " + this._hostURL);
        // raise the OnDisconnect event
        this._raiseEvent("OnDisconnect", null);
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnConnectError event.
    /// </summary>
    this.controlConnectErrorHandler = _controlConnectErrorHandler;
    function _controlConnectErrorHandler(){
        log.info("[" + this.Id + "]:  CitrixJavaTermClient failed to connect to: " + this._hostURL);
        // raise the OnConnectError event
        this._raiseEvent("OnConnectError", null);
    }

    /// <summary>
    /// Method gets the ActiveX or Applet control of the TermClient depending upon what 
    /// ControlPlatform has been deployed.
    /// </summary>
    /// <return type="object">the internal control, if this control has not been properly
    /// initialized this method ***can return null***</return>
    this.getControl = _getControl;
    function _getControl(){
        return this._control;
    }

    /// <summary>
    /// Method determines if the control is actually connected or not, helpful for polling 
    /// exercises and error checking in the URACoordinators.
    /// </summary>
    this.isConnected = _isConnected;
    function _isConnected(){
        try
        {
            if(this._control.isConnected()){
                log.info("[" + this.Id + "]:  CitrixJavaTermClient.isConnected returned: true");
                return true;
            } else {
                log.info("[" + this.Id + "]:  CitrixJavaTermClient.isConnected returned: false");
                return false;
            }
        }
        catch (e)
        {
            log.info("[" + this.Id + "]:  CitrixJavaTermClient.isConnected returned: false");
            return false;
        }
    }
}
// register this instance with the TermClientFactory
termClientFactory.registerTermClient(ControlPlatform.Applet, TermClientType.Citrix, "CitrixJavaTermClient");


/**********************************************************************
   $Author: csanford $
   $Date: 2008/04/16 16:05:23 $
   $Revision: 1.8 $


   Copyright 2001 - 2004. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/
/// <summary>
/// ESXVersion struct defines the version of ESX on the system
/// </summary>
ESXVersion = {
    /// <summary>
    /// Sets the version to 3.0
    /// </summary>
    v3_0 : 3.0,
    /// <summary>
    /// Sets the version to 3.5
    /// </summary>
    v3_5 : 3.5,
    /// <summary>
    /// Sets the version to the unsupported flag
    /// </summary>
    Unsupported : 99.0
};

/// <summary>
/// Esx3MessageType struct defines the type of message being sent by the control.
/// </summary>
Esx3MessageType = {
    /// <summary>
    /// The message type is a hint.
    /// </summary>
    Hint : 0,
    /// <summary>
    /// The message type is info.
    /// </summary>
    Info : 1,
    /// <summary>
    /// The message type is a warning.
    /// </summary>
    Warn : 2,
    /// <summary>
    /// The message type is an error.
    /// </summary>
    Error : 3
};

/// <summary>
/// Implementation class for the Esx3Console ActiveX TermClient object.
/// </summary>
/// <param name="id" type="string">the id of the TermClient instance</param>
function Esx3ConsoleActiveXTermClient(id){
/// region : inheritance --------------------------------------------
    this.base = TermClient;
    this.base(id);
    log.info("[" + id + "]:  Esx3ConsoleActiveXTermClient object created.");

/// region : private fields -----------------------------------------
    this._ctlSuffix = "_ax";

/// region : private fields -----------------------------------------
    this._termClientType = TermClientType.Esx3Console;
    this._control = null; // holds a reference to the HTML element
    this._connectCount = 25; // counter for the number of permissable connection attempts
    this._isConnectedf = false; // boolean switch set once the control has connected

/// region : Properties ---------------------------------------------

    /// <summary>
    /// Gets/sets the Protocol for this object.
    /// </summary>
    this.Protocol = TermClientProtocol.Esx3Console;

    /// <summary>
    /// Gets/sets the ControlPlatform for this object.
    /// </summary>
    this.Platform = ControlPlatform.ActiveX;

    /// <summary>
    /// Gets/sets the TermClientType for this object.
    /// </summary>
    this.TermClientType = TermClientType.Esx3Console;

/// region : Methods ------------------------------------------------

    /// <summary>
    /// Method handles any initialization needed for the control before the connect() method 
    /// is called.  Not all controls will implement the init() method therefore this is not 
    /// a "virtual" method, just an empty stub that must be overridden for any effect to occur.
    /// </summary>
    /// <param name="args" type="object">initialization arguments, this is dependent upon implementation</param>
    this.init = _init;
    function _init(args){
        // set the internal flags based on the host version string that was passed in
        if (this.HostVersion.indexOf("3.0") == 0){
            this.ESXVersion = ESXVersion.v3_0;
        } else if (this.HostVersion.indexOf("3.5") == 0){
            this.ESXVersion = ESXVersion.v3_5;
        } else {
            this.ESXVersion = ESXVersion.Unsupported;
        }
        if (browsercaps.isVista){
            // this plugin is not supported in Windows Vista
            log.info("[" + this.Id + "]:  Esx3ConsoleActiveXTermClient attempted to load in Windows Vista, but is unsupported.  Forcing OnLoadError event.");
            alert("Windows Vista is not supported by the ESX3 Console ActiveX control.  Please choose another connection type.");
            // return "abort" instead of false to prevent a connection attempt with the console applet...
            return "abort";
        }
        return true;
    }

    /// <summary>
    /// Method tells the TermClient to attempt to start the remote session. Raises 
    /// an OnConnect event.
    /// </summary>
    this.connect = _connect;
    function _connect(){        
        // create a counter for the number of connection attempts
        if(typeof(this._connectionAttempt) == "undefined"){
            this._connectionAttempt = 0;
        }
        try
        {
            // find our control and bind to it
            this._control = this.Element.getElementById(this.Id + this._ctlSuffix);
            if(this._control == null){
                log.error("[" + this.Id + "]:  Esx3ConsoleActiveXTermClient unable to find rendered object tag in document.");
                throw this._newError("No download error.");
            }
            log.debug("[" + this.Id + "]:  Esx3ConsoleActiveXTermClient._control = " + this._control);
            if(this._control == null || typeof(this._control.Connect) == "undefined"){
                log.info("[" + this.Id + "]:  Esx3ConsoleActiveXTermClient attempting connection:  " + this._connectionAttempt);
                if(this._connectionAttempt < this._connectCount){
                    this._connectionAttempt++;
                    this._setTimeout(this.Id + ".connect()", 1000);
                } else {
                    alert("You do not have the appropriate ActiveX control installed to connect via ESX3 Console.  Please choose another connection type or install the ActiveX control.");
                    this._raiseEvent("OnLoadError", null);
                }
            } else {
                log.info("[" + this.Id + "]:  Esx3ConsoleActiveXTermClient preparing to connect.");
                this._constrainSize();
                // NOTE: SetGuestSize is only supported in the ESX 3.0 version of the control
                if (typeof(this._control.SetGuestSize) != "undefined")
                {
                    this._control.SetGuestSize(this.Width, this.Height);
                }
                // set the global config settings
                //this._control.("", TerminalClientSettings.ColorDepth); // not supported
                //this._control.("", TerminalClientSettings.EnableSound); // not supported
                //this._control.("", TerminalClientSettings.EnableDriveMapping); // not supported
                this._control.Connect(this.HostAddress, this.HostPort, this.VmFile, this.HostUsername, this.HostPassword);
            }
        }
        catch (e)
        {
            if(e.message == "No download error."){
                log.fatal("[" + this.Id + "]:  Esx3ConsoleActiveXTermClient control unable to initialize due to download or installation error.");
            } else {
                log.fatal("[" + this.Id + "]:  Esx3ConsoleActiveXTermClient control suffered a fatal initialization error: " + e.message);
            }
            this._raiseEvent("OnConnectError", null);
        }
    }

    /// <summary>
    /// Method tells the TermClient to attempt to disconnect from the remote session.
    /// </summary>
    this.disconnect = _disconnect;
    function _disconnect(args) {
        try{
            this._control.Disconnect();
            log.info("[" + this.Id + "]:  Esx3ConsoleActiveXTermClient successfully disconnected from: " + this._hostURL);
        } catch (e){
            log.error("[" + this.Id + "]:  Esx3ConsoleActiveXTermClient suffered an error attempting to disconnect: " + e.message);
        }
    }

    /// <summary>
    /// Method renders the TermClient's HTML to the target frame's document.  The method 
    /// of render varies for each implementation.
    /// </summary>
    this.renderHtml = _renderHtml;
    function _renderHtml() {
        this._constrainSize();
        var ctlid = this.Id + this._ctlSuffix;
        // if the ESX client control is installed use its version, otherwise use the host's default version
        var version = this.ESXVersion;
        var control;
        try {
            // 3.0
            control = new ActiveXObject('QuickMksAx.QuickMksAxCtl.1');
            version = ESXVersion.v3_0;
        } catch (e) {
            try {
                // 3.5
                control = new ActiveXObject('QuickMksAx.QuickMksAxCtl.2.1');
                version = ESXVersion.v3_5;
            } catch (e) {}
        }
        control = null;
        // determine the appropriate CLSID and codebase URL based on the ESX version determined above
        var clsid;
        var url;
        switch (version){
            case ESXVersion.v3_0:
                clsid = "DC7D77DA-E1AC-4D40-930B-B87B2954E034";
                url = "https://" + this.HostAddress + "/ui/plugin/msie/vmware-mks.cab#version=2,0,1,0";
                break;
            case ESXVersion.v3_5:
            case ESXVersion.Unsupported:
            default:
                // TODO - assume 3.5 so don't have to modify URA for an ESX release if the cab isn't touched?
                clsid = "338095E4-1806-4ba3-AB51-38A3179200E9";
                url = "https://" + this.HostAddress + "/ui/plugin/msie/vmware-mks.cab#version=2,1,0,0";
                break;
        }
        // the control will be downloaded if necessary via the URA download proxy page...
        var codebase = appPath + '/DownloadProxy.aspx?URL=' + url;
        // build the script
        return '<object id="' + ctlid + '"' +
                    'classid="CLSID:' + clsid + '"' + 
                    'codebase="' + codebase + '"' + 
                    'width="' + this.Width + '" height="' + this.Height + '"' + 
                    'style="padding:0px;margin:0px;" >' + 
                '</object>' + 
                '<script type="text/javascript" for="' + ctlid + '" event="OnConnectionStateChange(connected)">' + 
                    'parent.' + this.Id + '.controlConnectionChangeHandler(connected);' +
                '</script>' + 
                '<script type="text/javascript" for="' + ctlid + '" event="OnSizeChange()">' + 
                    'parent.' + this.Id + '.controlResizeHandler();' +
                '</script>' + 
                '<script type="text/javascript" for="' + ctlid + '" event="OnMessage(type, message)">' + 
                    'parent.' + this.Id + '.controlMessageHandler(type, message);' +
                '</script>';
    }

    /// <summary>
    /// Method limits the size of this control to prevent errors.
    /// </summary>
    this._constrainSize = _constrainSize;
    function _constrainSize(){
        if(this.Width > 1600){
            log.info("[" + this.Id + "]:  Esx3ConsoleActiveXTermClient constraining width to: 1600px");
            this.Width = 1600;
        }
        if(this.Height > 1200){
            log.info("[" + this.Id + "]:  Esx3ConsoleActiveXTermClient constraining height to: 1200px");
            this.Height = 1200;
        }
    }

    /// <summary>
    /// Method to send Ctrl+Alt+Delete to the TermClient control
    /// </summary>
    this.sendCtrlAltDelete = _sendCtrlAltDelete;
    function _sendCtrlAltDelete(){
        if(this._control != null){
            this._control.SendCAD();
        }
    }

    /// <summary>
    /// Method to retrieve the key commands to send Ctrl+Alt+Delete to the TermClient control.
    /// </summary>
    this.getCADCommand = _getCADCommand;
    function _getCADCommand(){
        // return null because the key command is supported by the control.
        return null;
    }

    /// <summary>
    /// Callback event handler for the TermClient control's ConnectionChange event.
    /// </summary>
    this.controlConnectionChangeHandler = _controlConnectionChangeHandler;
    function _controlConnectionChangeHandler(connected){
        if(connected == true){
            this.controlConnectHandler();
        } else {
            if(this._isConnectedf == false){
                this.controlConnectErrorHandler();
            } else {
                this.controlDisconnectHandler();
            }
        }
    }

    /// <summary>
    /// Callback event handler for the TermClient control's OnMessage event.
    /// </summary>
    this.controlMessageHandler = _controlMessageHandler;
    function _controlMessageHandler(type, message){
        switch(type){
            case Esx3MessageType.Hint : 
                break;
            case Esx3MessageType.Info : 
                log.info("[" + this.Id + "]: Esx3ConsoleActiveXTermClient info: " + message);
                break;
            case Esx3MessageType.Warn : 
                log.warn("[" + this.Id + "]: Esx3ConsoleActiveXTermClient warning: " + message);
                break;
            case Esx3MessageType.Error : 
                log.warn("[" + this.Id + "]: Esx3ConsoleActiveXTermClient error: " + message);
                this.controlConnectErrorHandler();
                break;
        }
    }

    /// <summary>
    /// Callback event handler for the TermClient controls OnSizeChange event.
    /// </summary>
    this.controlResizeHandler = _controlResizeHandler;
    function _controlResizeHandler(){
        this._control.width = this._control.VMScreenWidth + 1;
        this._control.height = this._control.VMScreenHeight + 1;
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnConnect event.
    /// </summary>
    this.controlConnectHandler = _controlConnectHandler;
    function _controlConnectHandler(){
        log.info("[" + this.Id + "]:  Esx3ConsoleActiveXTermClient received connect event from the ActiveX control for: " + this._hostURL);
        // try to push the control to full screen if it supports it
        this._control.SetFullScreen(TerminalClientSettings.EnableFullScreen);
        // set the private _isConnectedf switch to true to indicate internally that we have successfully 
        // connected to the host
        this._isConnectedf = true;
        // raise the OnConnect event
        this._raiseEvent("OnConnect", null);
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnDisconnect event.
    /// </summary>
    this.controlDisconnectHandler = _controlDisconnectHandler;
    function _controlDisconnectHandler(){
        log.info("[" + this.Id + "]:  Esx3ConsoleActiveXTermClient received disconnect event from the ActiveX control for: " + this._hostURL);
        // because the control does not seem to raise the OnFatalError event due to failure to connect, the 
        // Esx3Console ActiveX control instead simply raises the OnDisconnect event.  However, if the control has 
        // never successfully connected, it is incorrect for the Esx3ConsoleActiveXTermClient to raise the OnDisconnect
        // event to the URACoordinator, rather we check the _isConnectedf switch and if this is false, we raise
        // the OnConnectError event
        if(this._isConnectedf){
            this._isConnectedf = false;
            // raise the OnDisconnect event
            this._raiseEvent("OnDisconnect", null);
        } else {
            // the control never successfully connected so raise the OnConnectError, using the event handler function
            this.controlConnectErrorHandler();
        }
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnConnectError event.
    /// </summary>
    this.controlConnectErrorHandler = _controlConnectErrorHandler;
    function _controlConnectErrorHandler(){
        log.info("[" + this.Id + "]:  Esx3ConsoleActiveXTermClient received connect error event from the ActiveX control for: " + this._hostURL);
        // raise the OnConnectError event
        this._raiseEvent("OnConnectError", null);
    }

    /// <summary>
    /// Method gets the ActiveX or Applet control of the TermClient depending upon what 
    /// ControlPlatform has been deployed.
    /// </summary>
    /// <return type="object">the internal control, if this control has not been properly
    /// initialized this method ***can return null***</return>
    this.getControl = _getControl;
    function _getControl(){
        return this._control;
    }

    /// <summary>
    /// Method determines if the control is actually connected or not, helpful for polling 
    /// exercises and error checking in the URACoordinators.
    /// </summary>
    this.isConnected = _isConnected;
    function _isConnected(){
        return this._isConnectedf;
    }
}
// register this instance with the TermClientFactory
termClientFactory.registerTermClient(ControlPlatform.ActiveX, TermClientType.Esx3Console, "Esx3ConsoleActiveXTermClient");


/**********************************************************************
   $Author: csanford $
   $Date: 2008/07/21 21:47:42 $
   $Revision: 1.10 $


   Copyright 2001 - 2004. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/
/// <summary>
/// ESXVersion struct defines the version of ESX on the system
/// </summary>
ESXVersion = {
    /// <summary>
    /// Sets the version to 3.0
    /// </summary>
    v3_0 : 3.0,
    /// <summary>
    /// Sets the version to 3.5
    /// </summary>
    v3_5 : 3.5,
    /// <summary>
    /// Sets the version to the unsupported flag
    /// </summary>
    Unsupported : 99.0
};

/// <summary>
/// Esx3MessageType struct defines the type of message being sent by the control.
/// </summary>
Esx3MessageType = {
    /// <summary>
    /// The message type is a hint.
    /// </summary>
    Hint : 1,
    /// <summary>
    /// The message type is info.
    /// </summary>
    Info : 2,
    /// <summary>
    /// The message type is a warning.
    /// </summary>
    Warn : 4,
    /// <summary>
    /// The message type is an error.
    /// </summary>
    Error : 8
};

/// <summary>
/// Implementation class for the Esx3Console Java TermClient object.
/// </summary>
/// <param name="id" type="string">the id of the TermClient instance</param>
function Esx3ConsoleJavaTermClient(id){
/// region : inheritance --------------------------------------------
    this.base = TermClient;
    this.base(id);
    log.info("[" + id + "]:  Esx3ConsoleJavaTermClient object created.");

/// region : private fields -----------------------------------------
    this._ctlSuffix = "_ax";

/// region : private fields -----------------------------------------
    this._termClientType = TermClientType.Esx3Console;
    this._control = null; // holds a reference to the HTML element
    this._connectCount = 25; // counter for the number of permissable connection attempts
    this._isRendered = false; // boolean switch set once the control has rendered
    this._isConnectedf = false; // boolean switch set once the control has connected
    this.IMessageListener = null; // ref to the IMessageListener interface
    this.IGrabStateListener = null; // ref to the IGragStateListener interface
    this.IWindowStateListener = null; // ref to the IWindowStateListener interface
    this.IConnectionStateListener = null; // ref to the IConnectionStateListener interface
    // add the plugin interface references
    if(!browsercaps.isIe){
        this.IMessageListener = Components.interfaces.xpcomIMessageListener;
        this.IGrabStateListener = Components.interfaces.xpcomIGrabStateListener;
        this.IWindowStateListener = Components.interfaces.xpcomIWindowStateListener;
        this.IConnectionStateListener = Components.interfaces.xpcomIConnectionStateListener;  
        this.ISizeChangeListener = Components.interfaces.xpcomISizeChangeListener;
    }

/// region : Properties ---------------------------------------------

    /// <summary>
    /// Gets/sets the Protocol for this object.
    /// </summary>
    this.Protocol = TermClientProtocol.Esx3Console;

    /// <summary>
    /// Gets/sets the ControlPlatform for this object.
    /// </summary>
    this.Platform = ControlPlatform.Applet;

    /// <summary>
    /// Gets/sets the TermClientType for this object.
    /// </summary>
    this.TermClientType = TermClientType.Esx3Console;

/// region : Methods ------------------------------------------------

    /// <summary>
    /// Method handles any initialization needed for the control before the connect() method 
    /// is called.  Not all controls will implement the init() method therefore this is not 
    /// a "virtual" method, just an empty stub that must be overridden for any effect to occur.
    /// </summary>
    /// <param name="args" type="object">initialization arguments, this is dependent upon implementation</param>
    this.init = _init;
    function _init(args){
        // set the internal flags based on the host version string that was passed in
        if (this.HostVersion.indexOf("3.0") == 0){
            this.ESXVersion = ESXVersion.v3_0;
        } else if (this.HostVersion.indexOf("3.5") == 0){
            this.ESXVersion = ESXVersion.v3_5;
        } else {
            this.ESXVersion = ESXVersion.Unsupported;
        }
        // this plugin is not supported in IE
        if(browsercaps.isIe){
            log.info("[" + this.Id + "]:  Esx3ConsoleJavaTermClient attempted to load in Internet Explorer, but is unsupported.  Forcing OnLoadError event.");
            //NOTE: This code can be executed after an Esx3ConsoleActiveXTermClient connect attempt fails in IE -
            //  don't display a message when it short circuits, otherwise it is confusing to the user
            return false;
        } else if (!(browsercaps.isWin || browsercaps.isWin32 || browsercaps.isUnix || browsercaps.isLinux)){
            // The Surgient plugin installation method only supports the windows, linux, and unix OSs,
            //      so error out if the plugin isn't already installed
            if (this.getInstalledPluginType() == null){
                log.info("[" + this.Id + "]:  Esx3ConsoleJavaTermClient attempted to load in an unsupported OS.  Forcing OnLoadError event.");
                alert("Your computer platform is not currently supported by the ESX3 Console.  Please choose another connection type or manually install the plugin control if possible.");
                return false;
            }
        } else if (browsercaps.isVista){
            // this plugin is not supported in Windows Vista
            log.info("[" + this.Id + "]:  Esx3ConsoleJavaTermClient attempted to load in Windows Vista, but is unsupported.  Forcing OnLoadError event.");
            alert("Windows Vista is not supported by the ESX3 Console plugin.  Please choose another connection type.");
            return false;
        }
        return true;
    }

    /// <summary>
    /// Method tells the TermClient to attempt to start the remote session. Raises 
    /// an OnConnect event.
    /// </summary>
    this.connect = _connect;
    function _connect(){
        // bail out if we failed to render the control (raise the connect event so that the download
        //      html will be shown)
        if (!this._isRendered){
            this._raiseEvent("OnConnect", null);
            return;
        }
        // create a counter for the number of connection attempts
        if(typeof(this._connectionAttempt) == "undefined"){
            this._connectionAttempt = 0;
        }
        try
        {
            // find our control and bind to it
            this._control = this.Element.getElementById(this.Id + this._ctlSuffix);
            if(this._control == null){
                log.error("[" + this.Id + "]:  Esx3ConsoleJavaTermClient unable to find rendered object tag in document.");
                throw this._newError("No download error.");
            }
            log.debug("[" + this.Id + "]:  Esx3ConsoleJavaTermClient._control = " + this._control);
            if(this._control == null || typeof(this._control.connect) == "undefined"){
                log.info("[" + this.Id + "]:  Esx3ConsoleJavaTermClient attempting connection:  " + this._connectionAttempt);
                if(this._connectionAttempt < this._connectCount){
                    this._connectionAttempt++;
                    this._setTimeout(this.Id + ".connect()", 1000);
                } else {
                    if(!browsercaps.isIe){
                        alert("You do not have the appropriate plugin control installed to connect via ESX3 Console.  Please choose another connection type or install the plugin control.");
                    }
                    this._raiseEvent("OnLoadError", null);
                }
            } else {
                log.info("[" + this.Id + "]:  Esx3ConsoleJavaTermClient preparing to connect.");
                this._constrainSize();
                this._hostURL = this.Protocol + "://" + this.HostAddress + ":" + this.HostPort + this.VmFile;
                // bind events to the control
                this._control.connectionStateListener = new Esx3ConsoleJavaTermClient_ConnectionStateListener(this);
                this._control.messageListener = new Esx3ConsoleJavaTermClient_MessageListener(this);
                this._control.sizeChangeListener = new Esx3ConsoleJavaTermClient_SizeChangeListener(this);
                // set the global config settings
                //this._control.("", TerminalClientSettings.ColorDepth); // not supported
                //this._control.("", TerminalClientSettings.EnableSound); // not supported
                //this._control.("", TerminalClientSettings.EnableDriveMapping); // not supported

                this._control.connect(this.HostAddress, this.HostPort, this.VmFile, this.HostUsername, this.HostPassword);
            }
        }
        catch (e)
        {
            if(e.message == "No download error."){
                log.fatal("[" + this.Id + "]:  Esx3ConsoleJavaTermClient control unable to initialize due to download or installation error.");
            } else {
                log.fatal("[" + this.Id + "]:  Esx3ConsoleJavaTermClient control suffered a fatal initialization error: " + e.message);
            }
            this._raiseEvent("OnConnectError", null);
        }
    }

    /// <summary>
    /// Method tells the TermClient to attempt to disconnect from the remote session.
    /// </summary>
    this.disconnect = _disconnect;
    function _disconnect(args) {
        try{
            this._control.disconnect();
            log.info("[" + this.Id + "]:  Esx3ConsoleJavaTermClient successfully disconnected from: " + this._hostURL);
        } catch (e){
            log.error("[" + this.Id + "]:  Esx3ConsoleJavaTermClient suffered an error attempting to disconnect: " + e.message);
        }
    }

    /// <summary>
    /// Method renders the TermClient's HTML to the target frame's document.  The method 
    /// of render varies for each implementation.
    /// </summary>
    this.renderHtml = _renderHtml;
    function _renderHtml() {
        this._constrainSize();
        // retrieve the installed mimetype for vmware-mks
        var controltype = this.getInstalledPluginType();
        // bail out if the plugin isn't installed
        if (controltype == null){
            // find and store the path to download and install the plugin
            //      (the OS is verified to be windows, unix, or linux in _init)
            // NOTE: the paths are consistent between ESX versions so far...
            var url;
            if(browsercaps.isWin || browsercaps.isWin32){
                url = "https://" + this.HostAddress + "/ui/plugin/mozilla/win32/vmware-mks.xpi";
            } else if (browsercaps.isUnix || browsercaps.isLinux){
                url = "https://" + this.HostAddress + "/ui/plugin/mozilla/linux/vmware-mks.xpi";
            } else {
                log.info("[" + this.Id + "]:  Esx3ConsoleJavaTermClient attempted to render in an unsupported OS.");
                url = "";
            }
            var link = appPath + '/DownloadProxy.aspx?URL=' + url;
            //NOTE: the link MUST be set to lowercase, otherwise FireFox prompts to download the file rather
            //  than install the plugin...
            return '<iframe id="pluginDownload" name="pluginDownload" src="' + appPath + '/blank.html" style="display:none"></iframe>' +
                '<table style="width:' + this.Width + 'px;height:' + this.Height + 'px;">' +
                '<tr><td style="vertical-align: middle; text-align: center;">' +
                '<h3>You do not have the appropriate plugin control installed to connect via ESX3 Console.</h3>' +
                '<p>Please click the "Install Missing Plugin" link to install (it may take several seconds to prompt you after clicking).</p>' +
                '<p>After the installation is complete, click the "Connect" link to try again.</p>' +
                '<a href="" onclick="window.frames[\'pluginDownload\'].location.href=\'' + link.toLowerCase() + '\';return false;">Install Missing Plugin</a>' +
                '<br/><a href="javascript:parent.' + this.Id + '._raiseEvent(\'OnDisconnect\', \'reconnect\');">Connect</a>' +
                '<br/><a href="javascript:parent.' + this.Id + '._raiseEvent(\'OnDisconnect\', null);">Cancel</a>' +
                '</td></tr></table>';
        }
        // set the private _isRendered flag to true to indicate internally that we have successfully 
        //      rendered the control
        this._isRendered = true;
        // render the plugin
        var ctlid = this.Id + this._ctlSuffix;
        return '<object id="' + ctlid + '" ' +
                    'type="' + controltype + '" ' +
                    'width="' + this.Width + '" height="' + this.Height + '" ' + 
                    'style="padding:0px;margin:0px;" >' + 
                '</object>';
    }

    /// <summary>
    /// Method retrieves the installed mime type for vmware mks.
    /// </summary>
    this.getInstalledPluginType = _getInstalledPluginType;
    function _getInstalledPluginType(){
        // refresh the plugin information in case they installed it in this session
        navigator.plugins.refresh(false);
        // check to see if the plugin is installed (mimeTypes is more reliable, iterating over plugins
        //      was crashing after installing one in the session)
        var pluginType = null;
        var searchStr = "application/x-vmware-mks";
        for(var i = 0; i < navigator.mimeTypes.length; i++){
            if(navigator.mimeTypes[i].type.indexOf(searchStr) != -1){
                pluginType = navigator.mimeTypes[i].type;
                break;
            }
        }
        return pluginType;
    }

    /// <summary>
    /// Method limits the size of this control to prevent errors.
    /// </summary>
    this._constrainSize = _constrainSize;
    function _constrainSize(){
        if(this.Width > 1600){
            log.info("[" + this.Id + "]:  Esx3ConsoleJavaTermClient constraining width to: 1600px");
            this.Width = 1600;
        }
        if(this.Height > 1200){
            log.info("[" + this.Id + "]:  Esx3ConsoleJavaTermClient constraining height to: 1200px");
            this.Height = 1200;
        }
    }

    /// <summary>
    /// Method to send Ctrl+Alt+Delete to the TermClient control
    /// </summary>
    this.sendCtrlAltDelete = _sendCtrlAltDelete;
    function _sendCtrlAltDelete(){
        if(this._control != null){
            this._control.sendCAD();
        }
    }

    /// <summary>
    /// Method to retrieve the key commands to send Ctrl+Alt+Delete to the TermClient control.
    /// </summary>
    this.getCADCommand = _getCADCommand;
    function _getCADCommand(){
        //return null because the key command is supported by the control
        return null;
    }

    /// <summary>
    /// Callback event handler for the TermClient control's ConnectionChange event.
    /// </summary>
    this.controlConnectionChangeHandler = _controlConnectionChangeHandler;
    function _controlConnectionChangeHandler(connected){
        if(connected == true){
            this.controlConnectHandler();
        } else {
            if(this._isConnectedf == false){
                this.controlConnectErrorHandler();
            } else {
                this.controlDisconnectHandler();
            }
        }
    }

    /// <summary>
    /// Callback event handler for the TermClient control's OnMessage event.
    /// </summary>
    this.controlMessageHandler = _controlMessageHandler;
    function _controlMessageHandler(type, message){
        switch(type){
            case Esx3MessageType.Hint : 
                break;
            case Esx3MessageType.Info : 
                log.info("[" + this.Id + "]: Esx3ConsoleJavaTermClient info: " + message);
                break;
            case Esx3MessageType.Warn : 
                log.warn("[" + this.Id + "]: Esx3ConsoleJavaTermClient warning: " + message);
                break;
            case Esx3MessageType.Error : 
                log.error("[" + this.Id + "]: Esx3ConsoleJavaTermClient error: " + message);
                this.controlConnectErrorHandler();
                break;
        }
    }

    /// <summary>
    /// Callback event handler for the TermClient controls OnSizeChange event.
    /// </summary>
    this.controlResizeHandler = _controlResizeHandler;
    function _controlResizeHandler(){
        this._control.width = this._control.vmScreenWidth + 1;
        this._control.height = this._control.vmScreenHeight + 1;
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnConnect event.
    /// </summary>
    this.controlConnectHandler = _controlConnectHandler;
    function _controlConnectHandler(){
        log.info("[" + this.Id + "]:  Esx3ConsoleJavaTermClient received connect event from the Java control for: " + this._hostURL);
        // try to push the control to full screen if it supports it
        this._control.setFullScreen(TerminalClientSettings.EnableFullScreen);
        // set the private _isConnectedf switch to true to indicate internally that we have successfully 
        // connected to the host
        this._isConnectedf = true;
        // raise the OnConnect event
        this._raiseEvent("OnConnect", null);
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnDisconnect event.
    /// </summary>
    this.controlDisconnectHandler = _controlDisconnectHandler;
    function _controlDisconnectHandler(){
        log.info("[" + this.Id + "]:  Esx3ConsoleJavaTermClient received disconnect event from the Java control for: " + this._hostURL);
        // because the control does not seem to raise the OnFatalError event due to failure to connect, the 
        // Esx3Console Java control instead simply raises the OnDisconnect event.  However, if the control has 
        // never successfully connected, it is incorrect for the Esx3ConsoleJavaTermClient to raise the OnDisconnect
        // event to the URACoordinator, rather we check the _isConnectedf switch and if this is false, we raise
        // the OnConnectError event
        if(this._isConnectedf){
            this._isConnectedf = false;
            // raise the OnDisconnect event
            this._raiseEvent("OnDisconnect", null);
        } else {
            // the control never successfully connected so raise the OnConnectError, using the event handler function
            this.controlConnectErrorHandler();
        }
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnConnectError event.
    /// </summary>
    this.controlConnectErrorHandler = _controlConnectErrorHandler;
    function _controlConnectErrorHandler(){
        log.info("[" + this.Id + "]:  Esx3ConsoleJavaTermClient received connect error event from the Java control for: " + this._hostURL);
        // raise the OnConnectError event
        this._raiseEvent("OnConnectError", null);
    }

    /// <summary>
    /// Method gets the Java or Applet control of the TermClient depending upon what 
    /// ControlPlatform has been deployed.
    /// </summary>
    /// <return type="object">the internal control, if this control has not been properly
    /// initialized this method ***can return null***</return>
    this.getControl = _getControl;
    function _getControl(){
        return this._control;
    }

    /// <summary>
    /// Method determines if the control is actually connected or not, helpful for polling 
    /// exercises and error checking in the URACoordinators.
    /// </summary>
    this.isConnected = _isConnected;
    function _isConnected(){
        return this._isConnectedf;
    }
}

/// <summary>
/// Implements ConnectionStateListener, delegates to Esx3ConsoleJavaTermClient
/// <summary>
function Esx3ConsoleJavaTermClient_ConnectionStateListener(termClient) {
    this._termClient = termClient;

    /// <summary>
    /// Invoked by Firefox plugin on connection state change
    /// </summary>
    this.onConnectionStateChange = _onConnectionStateChange;
    function _onConnectionStateChange(connected) {
        this._termClient.controlConnectionChangeHandler(connected);
    }
}

/// <summary>
/// Implements MessageListener, delegates to Esx3ConsoleJavaTermClient
/// <summary>
function Esx3ConsoleJavaTermClient_MessageListener(termClient) {
    this._termClient = termClient;

    /// <summary>
    /// Invoked by Firefox plugin on info/warn/error messages
    /// </summary>
    this.onMessage = _onMessage;
    function _onMessage(msgType, message) {
        this._termClient.controlMessageHandler(msgType, message);
    }
}

/// <summary>
/// Implements SizeChangeListener, delegates to Esx3ConsoleJavaTermClient
/// </summary>
function Esx3ConsoleJavaTermClient_SizeChangeListener(termClient) {
    this._termClient = termClient;

    /// <summary>
    /// Invoked by Firefox plugin on size change event
    /// </summary>
    this.onSizeChange = _onSizeChange;
    function _onSizeChange() {
        this._termClient.controlResizeHandler();
    }
}

// register this instance with the TermClientFactory
termClientFactory.registerTermClient(ControlPlatform.Applet, TermClientType.Esx3Console, "Esx3ConsoleJavaTermClient");


/**********************************************************************
   $Author: dbabbitt $
   $Date: 2007/06/13 16:04:04 $
   $Revision: 1.12 $


   Copyright 2001 - 2004. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/
/// <summary>
/// MvsConnectionState struct defines the available connection states for the  
/// MvsConsole TermClient
/// </summary>
MvsConnectionState = {
    /// <summary>
    /// Sets the state as not connected.
    /// </summary>
    NotConnected : 0,
    /// <summary>
    /// Sets the state as connecting.
    /// </summary>
    Connecting : 1,
    /// <summary>
    /// Sets the state as authenticating.
    /// </summary>
    Authenticating : 2,
    /// <summary>
    /// Sets the state as connecting.
    /// </summary>
    Connected : 3,
    /// <summary>
    /// Sets the state as connection failed.
    /// </summary>
    ConnectionFailed : 4
};

/// <summary>
/// Implementation class for the MvsConsole ActiveX TermClient object.
/// </summary>
/// <param name="id" type="string">the id of the TermClient instance</param>
function MvsConsoleActiveXTermClient(id){
/// region : inheritance --------------------------------------------
    this.base = TermClient;
    this.base(id);
    log.info("[" + id + "]:  MvsConsoleActiveXTermClient object created.");

/// region : private fields -----------------------------------------
    this._ctlSuffix = "_ax";

/// region : private fields -----------------------------------------
    this._termClientType = TermClientType.MvsConsole;
    this._control = null; // holds a reference to the HTML element
    this._connectCount = 25; // counter for the number of permissable connection attempts
    this._successfulConnect = false; // switch for indicating when the control has successfully connected

/// region : Properties ---------------------------------------------

    /// <summary>
    /// Gets/sets the Protocol for this object.
    /// </summary>
    this.Protocol = TermClientProtocol.MvsConsole;

    /// <summary>
    /// Gets/sets the ControlPlatform for this object.
    /// </summary>
    this.Platform = ControlPlatform.ActiveX;

    /// <summary>
    /// Gets/sets the TermClientType for this object.
    /// </summary>
    this.TermClientType = TermClientType.MvsConsole;

/// region : Methods ------------------------------------------------

    /// <summary>
    /// Method handles any initialization needed for the control before the connect() method 
    /// is called.  Not all controls will implement the init() method therefore this is not 
    /// a "virtual" method, just an empty stub that must be overridden for any effect to occur.
    /// </summary>
    /// <param name="args" type="object">initialization arguments, this is dependent upon implementation</param>
    this.init = _init;
    function _init(args){
        // no noop call here, if a control does not override, fail silently.
        return;
    }

    /// <summary>
    /// Method tells the TermClient to attempt to start the remote session. Raises 
    /// an OnConnect event.
    /// </summary>
    this.connect = _connect;
    function _connect(){        
        // create a counter for the number of connection attempts
        if(typeof(this._connectionAttempt) == "undefined"){
            this._connectionAttempt = 0;
        }
        try
        {
            // find our control and bind to it
            this._control = this.Element.getElementById(this.Id + this._ctlSuffix);
            if(this._control == null){
                log.error("[" + this.Id + "]:  MvsConsoleActiveXTermClient unable to find rendered object tag in document.");
                throw this._newError("No download error.");
            }
            log.debug("[" + this.Id + "]:  MvsConsoleActiveXTermClient._control = " + this._control);
            if(this._control == null || typeof(this._control.Connect) == "undefined"){
                log.info("[" + this.Id + "]:  MvsConsoleActiveXTermClient attempting connection:  " + this._connectionAttempt);
                if(this._connectionAttempt < this._connectCount){
                    this._connectionAttempt++;
                    this._setTimeout(this.Id + ".connect()", 1000);
                } else {
                    this._raiseEvent("OnLoadError", null);
                }
            } else {
                log.info("[" + this.Id + "]:  MvsConsoleActiveXTermClient preparing to connect.");
                this._control.ServerAddress = this.HostAddress;
                this._hostURL = this.Protocol + "://" + this.HostAddress + ":" + this.HostPort;
                // set the username & password
                this._control.UserName = this.HostUsername;
                this._control.UserPassword = this.HostPassword;
                this._control.ServerPort = this.HostPort;
                this._control.ServerDisplayName = this.VmName;
                // set the global config settings
                //TerminalClientSettings.ColorDepth // not supported
                //TerminalClientSettings.EnableSound // not supported
                //TerminalClientSettings.EnableFullScreen // not supported
                //TerminalClientSettings.EnableDriveMapping // not supported
                this._control.Connect();
            }
        }
        catch (e)
        {
            if(e.message == "No download error."){
                log.fatal("[" + this.Id + "]:  MvsConsoleActiveXTermClient control unable to initialize due to download or installation error.");
            } else {
                log.fatal("[" + this.Id + "]:  MvsConsoleActiveXTermClient control suffered a fatal initialization error: " + e.message);
            }
            this._raiseEvent("OnConnectError", null);
        }
    }

    /// <summary>
    /// Method tells the TermClient to attempt to disconnect from the remote session.
    /// </summary>
    this.disconnect = _disconnect;
    function _disconnect(args) {
        try{
            this._control.Disconnect();
            log.info("[" + this.Id + "]:  MvsConsoleActiveXTermClient successfully disconnected from: " + this._hostURL);
        } catch (e){
            log.error("[" + this.Id + "]:  MvsConsoleActiveXTermClient suffered an error attempting to disconnect: " + e.message);
        }
    }

    /// <summary>
    /// Method renders the TermClient's HTML to the target frame's document.  The method 
    /// of render varies for each implementation.
    /// </summary>
    this.renderHtml = _renderHtml;
    function _renderHtml() {
        var ctlid = this.Id + this._ctlSuffix;
        return '<object id="' + ctlid + '"' + 
                    'classid="CLSID:04A24971-3E8B-439D-9CC4-C6FE1D02EF50"' + 
                    'codebase="' + appPath + '/URA/lib/smvsvmrc.cab#Version=5,3,0,0"' + 
                    'width="' + this.Width + '" height="' + this.Height + '"' + 
                    'style="padding:0px;margin:0px;" >' + 
                    '<param name="AdministratorMode" value="false" />' + 
                    '<param name="MenuEnabled" value="false" />' + 
                    '<param name="AutoSize" value="true" />' + 
                '</object>' + 
				'<SCRIPT language="javascript" for="' + ctlid + '" event="OnSwitchedDisplay(vmrcState)" type="text/javascript">' + 
                'parent.' + this.Id + '.controlViewSwitchHandler();</SCRIPT>' + 
                '<SCRIPT language="javascript" for="' + ctlid + '" event="OnStateChanged(vmrcState)" type="text/javascript">' + 
                'parent.' + this.Id + '.controlStateChangeHandler(vmrcState);</SCRIPT>';
    }

    /// <summary>
    /// Method to send Ctrl+Alt+Delete to the TermClient control
    /// </summary>
    this.sendCtrlAltDelete = _sendCtrlAltDelete;
    function _sendCtrlAltDelete(){
        this._control.SendKeySequence("DOWN,Key_RightCtrl,DOWN,Key_RightAlt,DOWN,Key_Delete,HOLD,UP,Key_RightCtrl,UP,Key_RightAlt,UP,Key_Delete");
    }

    /// <summary>
    /// Method to retrieve the key commands to send Ctrl+Alt+Delete to the TermClient control.
    /// </summary>
    this.getCADCommand = _getCADCommand;
    function _getCADCommand(){
        // send null because the key command is supported by the control
        return null;
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnStateChanged event.
    /// </summary>
    this.controlStateChangeHandler = _controlStateChangeHandler;
    function _controlStateChangeHandler(state){
        switch (state)
        {
        case MvsConnectionState.NotConnected :
            if(this._successfulConnect){
                this.controlDisconnectHandler();
            }
            break;
        case MvsConnectionState.Connecting :
            // do nothing with this state.
            break;
        case MvsConnectionState.Authenticating :
            // do nothing with this state.
            break;
        case MvsConnectionState.Connected :
            if(this._control.ServerDisplayName == this.VmName){
                this.controlConnectHandler();
            } else {
                this.controlConnectErrorHandler();
            }
            break;
        case MvsConnectionState.ConnectionFailed :
            this.controlConnectErrorHandler();
            break;
        }
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnSwitchedDisplay event.
    /// </summary>
	this.controlViewSwitchHandler = _controlViewSwitchHandler;
	function _controlViewSwitchHandler(){
		var dispName = this._control.ServerDisplayName;
		if(this._successfulConnect == true){
			// if we have previously connected, then any time the display 
			// changes to a different server we need to disconnect the control and 
			// raise the disconnect event
			if(dispName != this.VmName){
			    this._control.Disconnect();	
			}
		} else {
			// if we have not previously connected, then any time the display
            // changes to a different server we need to disconnect the control and 
            // raise the connecterror event
            if(dispName != this.VmName){
                this.controlConnectErrorHandler();
            }
		}
	}

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnConnect event.
    /// </summary>
    this.controlConnectHandler = _controlConnectHandler;
    function _controlConnectHandler(){
        log.info("[" + this.Id + "]:  MvsConsoleActiveXTermClient received connect event from the ActiveX control for: " + this._hostURL);
        this._successfulConnect = true;
        this.Width = this._control.ServerDisplayWidth;
        this.Height = this._control.ServerDisplayHeight;
        // raise the OnConnect event
        this._raiseEvent("OnConnect", null);
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnDisconnect event.
    /// </summary>
    this.controlDisconnectHandler = _controlDisconnectHandler;
    function _controlDisconnectHandler(){
        log.info("[" + this.Id + "]:  MvsConsoleActiveXTermClient received disconnect event from the ActiveX control for: " + this._hostURL);
        this._successfulConnect = false;
        // raise the OnDisconnect event
        this._raiseEvent("OnDisconnect", null);
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnConnectError event.
    /// </summary>
    this.controlConnectErrorHandler = _controlConnectErrorHandler;
    function _controlConnectErrorHandler(){
        log.info("[" + this.Id + "]:  MvsConsoleActiveXTermClient received connect error event from the ActiveX control for: " + this._hostURL);
        this._successfulConnect = false;
        // raise the OnConnectError event
        this._raiseEvent("OnConnectError", null);
    }

    /// <summary>
    /// Method gets the ActiveX or Applet control of the TermClient depending upon what 
    /// ControlPlatform has been deployed.
    /// </summary>
    /// <return type="object">the internal control, if this control has not been properly
    /// initialized this method ***can return null***</return>
    this.getControl = _getControl;
    function _getControl(){
        return this._control;
    }

    /// <summary>
    /// Method determines if the control is actually connected or not, helpful for polling 
    /// exercises and error checking in the URACoordinators.
    /// </summary>
    this.isConnected = _isConnected;
    function _isConnected(){
        if(typeof(this._control.State) != "undefined"){
            if(this._control.State == MvsConnectionState.Connected){
                log.info("[" + this.Id + "]:  MvsConsoleActiveXTermClient.isConnected returned: true");
                return true;
            } else {
                log.info("[" + this.Id + "]:  MvsConsoleActiveXTermClient.isConnected returned: false");
                return false;
            }
        } else {
            log.info("[" + this.Id + "]:  MvsConsoleActiveXTermClient.isConnected returned: false");
            return false;
        }
    }
}
// register this instance with the TermClientFactory
termClientFactory.registerTermClient(ControlPlatform.ActiveX, TermClientType.MvsConsole, "MvsConsoleActiveXTermClient");


/**********************************************************************
   $Author: greynold $
   $Date: 2007/05/23 18:36:54 $
   $Revision: 1.5 $


   Copyright 2001 - 2004. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/
/// <summary>
/// Implementation class for the MvsConsole Applet TermClient object.
/// </summary>
/// <param name="id" type="string">the id of the TermClient instance</param>
function MvsConsoleJavaTermClient(id){
/// region : inheritance --------------------------------------------
    this.base = TermClient;
    this.base(id);
    log.info("[" + id + "]:  MvsConsoleJavaTermClient object created.");

/// region : private fields -----------------------------------------
    this._ctlSuffix = "_ax";

/// region : private fields -----------------------------------------
    this._termClientType = TermClientType.MvsConsole;
    this._control = null; // holds a reference to the HTML element
    this._connectCount = 25; // counter for the number of permissable connection attempts
    this._successfulConnect = false; // switch for indicating when the control has successfully connected

/// region : Properties ---------------------------------------------

    /// <summary>
    /// Gets/sets the Protocol for this object.
    /// </summary>
    this.Protocol = TermClientProtocol.MvsConsole;

    /// <summary>
    /// Gets/sets the ControlPlatform for this object.
    /// </summary>
    this.Platform = ControlPlatform.Applet;

    /// <summary>
    /// Gets/sets the TermClientType for this object.
    /// </summary>
    this.TermClientType = TermClientType.MvsConsole;

/// region : Methods ------------------------------------------------

    /// <summary>
    /// Method handles any initialization needed for the control before the connect() method 
    /// is called.  Not all controls will implement the init() method therefore this is not 
    /// a "virtual" method, just an empty stub that must be overridden for any effect to occur.
    /// </summary>
    /// <param name="args" type="object">initialization arguments, this is dependent upon implementation</param>
    this.init = _init;
    function _init(args){
        // no noop call here, if a control does not override, fail silently.
        return;
    }

    /// <summary>
    /// Method tells the TermClient to attempt to start the remote session. Raises 
    /// an OnConnect event.
    /// </summary>
    this.connect = _connect;
    function _connect(){        
        log.info("[" + this.Id + "]:  MvsConsoleJavaTermClient preparing to connect.");
        // create a quick exit for this control in InternetExplorer
        // since it can be reached via a platform failover event and mislead the user 
        // into thinking a connection failure is a result of misconfiguration
        if(browsercaps.isIe){
            log.info("[" + this.Id + "]:  MvsConsoleJavaTermClient aborting processing for Internet Explorer.");
            this.controlConnectErrorHandler();
        } else {
            // there is no control to activate so call the connect event handler and message onconnect
            this.controlConnectHandler();
        }
    }

    /// <summary>
    /// Method tells the TermClient to attempt to disconnect from the remote session.
    /// </summary>
    this.disconnect = _disconnect;
    function _disconnect(args) {
        log.info("[" + this.Id + "]:  MvsConsoleJavaTermClient successfully disconnected from: " + this._hostURL);
        this.controlDisconnectHandler();
    }

    /// <summary>
    /// Method renders the TermClient's HTML to the target frame's document.  The method 
    /// of render varies for each implementation.
    /// </summary>
    this.renderHtml = _renderHtml;
    function _renderHtml() {
        var ctlid = this.Id + this._ctlSuffix;
        if(!browsercaps.isIe){
            return '<div style="text-align:center;padding-top:50px;width:' + this.Width + 'px;height:' + this.Height + 'px;">' + 
                '<h2>This access method is only supported in Internet Explorer with ActiveX controls enabled.</h2>' +
                '</div>';
        } else {

        }
    }

    /// <summary>
    /// Method to send Ctrl+Alt+Delete to the TermClient control
    /// </summary>
    this.sendCtrlAltDelete = _sendCtrlAltDelete;
    function _sendCtrlAltDelete(){
        alert("This remote access method is only supported in Internet Explorer with ActiveX controls enabled.");
    }

    /// <summary>
    /// Method to retrieve the key commands to send Ctrl+Alt+Delete to the TermClient control.
    /// </summary>
    this.getCADCommand = _getCADCommand;
    function _getCADCommand(){
        // send null because the key command is supported by the control
        return null;
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnConnect event.
    /// </summary>
    this.controlConnectHandler = _controlConnectHandler;
    function _controlConnectHandler(){
        log.info("[" + this.Id + "]:  MvsConsoleJavaTermClient received connect event from the Applet control for: " + this._hostURL);
        this._raiseEvent("OnConnect", null);
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnDisconnect event.
    /// </summary>
    this.controlDisconnectHandler = _controlDisconnectHandler;
    function _controlDisconnectHandler(){
        log.info("[" + this.Id + "]:  MvsConsoleJavaTermClient received disconnect event from the Applet control for: " + this._hostURL);
        // raise the OnDisconnect event
        this._raiseEvent("OnDisconnect", null);
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnConnectError event.
    /// </summary>
    this.controlConnectErrorHandler = _controlConnectErrorHandler;
    function _controlConnectErrorHandler(){
        log.info("[" + this.Id + "]:  MvsConsoleJavaTermClient received connect error event from the Applet control for: " + this._hostURL);
        // raise the OnConnectError event
        this._raiseEvent("OnConnectError", null);
    }

    /// <summary>
    /// Method gets the Applet or Applet control of the TermClient depending upon what 
    /// ControlPlatform has been deployed.
    /// </summary>
    /// <return type="object">the internal control, if this control has not been properly
    /// initialized this method ***can return null***</return>
    this.getControl = _getControl;
    function _getControl(){
        return null;
    }

    /// <summary>
    /// Method determines if the control is actually connected or not, helpful for polling 
    /// exercises and error checking in the URACoordinators.
    /// </summary>
    this.isConnected = _isConnected;
    function _isConnected(){
        log.info("[" + this.Id + "]:  MvsConsoleJavaTermClient.isConnected returned: true");
        return true;
    }
}
// register this instance with the TermClientFactory
termClientFactory.registerTermClient(ControlPlatform.Applet, TermClientType.MvsConsole, "MvsConsoleJavaTermClient");


/**********************************************************************
   $Author: csanford $
   $Date: 2008/08/06 22:13:34 $
   $Revision: 1.26 $


   Copyright 2001 - 2007. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/

/// <summary>
/// Implementation class for the RDP ActiveX TermClient object.
/// </summary>
/// <param name="id" type="string">the id of the TermClient instance</param>
function RDPActiveXTermClient(id){
/// region : inheritance --------------------------------------------
    this.base = TermClient;
    this.base(id);
    log.info("[" + id + "]:  RDPActiveXTermClient object created.");

/// region : private fields -----------------------------------------
    this._ctlSuffix = "_ax";

/// region : private fields -----------------------------------------
    this._termClientType = TermClientType.RDP;
    this._control = null; // holds a reference to the HTML element
    this._connectCount = 25; // counter for the number of permissable connection attempts
    this._hasConnected = false; // boolean switch set once the control has connected

/// region : Properties ---------------------------------------------

    /// <summary>
    /// Gets/sets the Protocol for this object.
    /// </summary>
    this.Protocol = TermClientProtocol.RDP;

    /// <summary>
    /// Gets/sets the ControlPlatform for this object.
    /// </summary>
    this.Platform = ControlPlatform.ActiveX;

    /// <summary>
    /// Gets/sets the TermClientType for this object.
    /// </summary>
    this.TermClientType = TermClientType.RDP;

/// region : Methods ------------------------------------------------

    /// <summary>
    /// Method handles any initialization needed for the control before the connect() method 
    /// is called.  Not all controls will implement the init() method therefore this is not 
    /// a "virtual" method, just an empty stub that must be overridden for any effect to occur.
    /// </summary>
    /// <param name="args" type="object">initialization arguments, this is dependent upon implementation</param>
    this.init = _init;
    function _init(args){
        // no noop call here, if a control does not override, fail silently.
        return;
    }

    /// <summary>
    /// Wait for the control to become available, then call _controlConnect().
    /// </summary>
    this.connect = _connect;
    function _connect(isControlCalling){
        // bail out if this is not the call from controlReadyStateChangeHandler
        //  (see the comments for that function for more details) 
        if (!isControlCalling){
            if (this._control && this._controlIsConnected()){
                // cancel the timeout interval since the control call already connected
                this._raiseEvent("OnCancelInterval", null);
            }
            log.info("[" + this.Id + "]:  RDPActiveXTermClient aborting URACoordinator connect call.");
            return;
        }
        // create a counter for the number of connection attempts
        if(typeof(this._connectionAttempt) == "undefined"){
            this._connectionAttempt = 0;
        }
        try
        {
            // find our control and bind to it
            if(this._control == null){
                this._control = this.Element.getElementById(this.Id + this._ctlSuffix);
                if(this._control == null){
                    log.error("[" + this.Id + "]:  RDPActiveXTermClient unable to find rendered object tag in document.");
                    throw this._newError("No download error.");
                }
            }
            log.debug("[" + this.Id + "]:  RDPActiveXTermClient._control = " + this._control);
            if(this._control == null || typeof(this._control.Connect) == "undefined"){
                log.info("[" + this.Id + "]:  RDPActiveXTermClient attempting connection:  " + this._connectionAttempt);
                if(this._connectionAttempt < this._connectCount){
                    this._connectionAttempt++;
                    this._setTimeout(this.Id + ".connect()", 1000);
                } else {
                    this._raiseEvent("OnLoadError", null);
                }
            } else {
                this._constrainSize();
                this._hostURL = this.Protocol + "://" + this.HostAddress + ":" + this.HostPort;
                this._controlConnect();
            }
        }
        catch (e)
        {
            if(e.message == "No download error."){
                log.fatal("[" + this.Id + "]:  RDPActiveXTermClient control unable to initialize due to download or installation error.");
            } else {
                log.fatal("[" + this.Id + "]:  RDPActiveXTermClient control suffered a fatal initialization error: " + e.message);
            }
            this._raiseEvent("OnConnectError", null);
        }
    }

    /// <summary>
    /// Direct the control to connect to the server.
    /// </summary>
    this._controlConnect = _controlConnect;
    function _controlConnect(){
        log.info("[" + this.Id + "]:  RDPActiveXTermClient preparing to connect.");
        if(!TerminalClientSettings.EnableFullScreen){
            this._control.DesktopWidth = this.Width;
            this._control.DesktopHeight = this.Height;
        }
        
        this._control.Server = this.HostAddress;
        this._control.AdvancedSettings2.RDPPort = this.HostPort;
        this._control.Domain = "";
        this._control.UserName = this.Username;
        this._control.AdvancedSettings2.ClearTextPassword = this.Password;
        // set the global config settings
        var colorDepth;
        switch(TerminalClientSettings.ColorDepth){
            case 8 : 
                colorDepth = 8;
                break;
            case 16 : 
                colorDepth = 16;
                break;
            default :
                colorDepth = 24;
        }
        this._control.ColorDepth = colorDepth;
        //this._control = TerminalClientSettings.EnableSound // not supported
        this._control.FullScreen = TerminalClientSettings.EnableFullScreen;
        //this._control = TerminalClientSettings.EnableDriveMapping // not supported
        this._control.Connect();
    }

    /// <summary>
    /// Method tells the TermClient to attempt to disconnect from the remote session.
    /// </summary>
    this.disconnect = _disconnect;
    function _disconnect(args) {
        try{
            this._control.Disconnect();
            log.info("[" + this.Id + "]:  RDPActiveXTermClient successfully disconnected from: " + this._hostURL);
        } catch (e){
            log.error("[" + this.Id + "]:  RDPActiveXTermClient suffered an error attempting to disconnect: " + e.message);
        }
    }

    /// <summary>
    /// Method renders the TermClient's HTML to the target frame's document.  The method 
    /// of render varies for each implementation.
    /// </summary>
    this.renderHtml = _renderHtml;
    function _renderHtml() {
        // setting the width/height of the object interferes with full screen mode so 
        // drop these values if in that mode
        if(TerminalClientSettings.EnableFullScreen){
            this.Width = screen.width;
            this.Height = screen.height;
        }
        this._constrainSize();
        var ctlid = this.Id + this._ctlSuffix;
        return '<object id="' + ctlid + '"' +
                    'classid="CLSID:4EDCB26C-D24C-4E72-AF07-B576699AC0DE"' + 
                    'codebase="' + appPath + '/URA/lib/srdp.cab#Version=5,2,3790,1830"' + 
                    'width="' + this.Width + '" height="' + this.Height + '"' + 
                    'style="padding:0px;margin:0px;"' +
                    'OnReadyStateChange="parent.' + this.Id + '.controlReadyStateChangeHandler(this)"' +
                    '>' + 
                '</object>' + 
                '<script type="text/javascript" for="' + ctlid + '" event="OnDisconnected(reason)">' + 
                    'parent.' + this.Id + '.controlDisconnectHandler(reason);' +
                '</script>' + 
                '<script type="text/javascript" for="' + ctlid + '" event="OnFatalError(error)">' + 
                    'parent.' + this.Id + '.controlConnectErrorHandler(error);' +
                '</script>' + 
                '<script type="text/javascript" for="' + ctlid + '" event="OnConnected()">' + 
                    'parent.' + this.Id + '.controlConnectHandler();' +
                '</script>' +
                '<script type="text/javascript" for="' + ctlid + '" event="OnChannelReceivedData(chanName, data)">' + 
                    'parent.' + this.Id + '.controlChannelRecvHandler(chanName, data);' +
                '</script>' +
                '<script type="text/javascript" for="' + ctlid + '" event="OnAutoReconnecting(disconnectReason, attemptCount)">' + 
                    'parent.' + this.Id + '.controlAutoReconnectingHandler(disconnectReason, attemptCount);' +
                '</script>';
    }

    /// <summary>
    /// Method limits the size of this control to prevent errors.
    /// </summary>
    this._constrainSize = _constrainSize;
    function _constrainSize(){
        if(this.Width > 1600){
            log.info("[" + this.Id + "]:  RDPActiveXTermClient constraining width to: 1600px");
            this.Width = 1600;
        }
        if(this.Height > 1200){
            log.info("[" + this.Id + "]:  RDPActiveXTermClient constraining height to: 1200px");
            this.Height = 1200;
        }
    }

    /// <summary>
    /// Method to send Ctrl+Alt+Delete to the TermClient control
    /// </summary>
    this.sendCtrlAltDelete = _sendCtrlAltDelete;
    function _sendCtrlAltDelete(){
        alert("To send CTRL+ALT+DEL use the following key combination:\n\tCTRL+ALT+END");
    }

    /// <summary>
    /// Method to retrieve the key commands to send Ctrl+Alt+Delete to the TermClient control.
    /// </summary>
    this.getCADCommand = _getCADCommand;
    function _getCADCommand(){
        return "CTRL+ALT+END";
    }

    /// <summary>
    /// Event handler for the ActiveX control OnConnected event.
    /// </summary>
    this.controlConnectHandler = _controlConnectHandler;
    function _controlConnectHandler(){
        log.info("[" + this.Id + "]:  RDPActiveXTermClient received connect event from the ActiveX control for: " + this._hostURL);
        // set the private _hasConnected switch to true to indicate internally that we have successfully 
        // connected to the host
        this._hasConnected = true;
        // raise the OnConnect event
        this._raiseEvent("OnConnect", null);
    }

    /// <summary>
    /// Event handler for the ActiveX control OnDisconnected event.
    /// </summary>
    this.controlDisconnectHandler = _controlDisconnectHandler;
    function _controlDisconnectHandler(reason){
        log.info("[" + this.Id + "]:  RDPActiveXTermClient received disconnect event from the ActiveX control for: " + this._hostURL + ", code: " + reason);
        // The control does not seem to raise the OnFatalError event
        // due to failure to connect, the RDP ActiveX control instead simply
        // raises the OnDisconnect event.  However, if the control has 
        // never successfully connected, it is incorrect for this TermClient to
        // raise the OnDisconnect event to the URACoordinator, rather we check
        // the _hasConnected switch and if this is false, we raise
        // the OnConnectError event
        if(this._hasConnected){
            this._hasConnected = false;
            // raise the OnDisconnect event
            this._raiseEvent("OnDisconnect", null);
        } else {
            // the control never successfully connected so raise the OnConnectError, using the event handler function
            this.controlConnectErrorHandler(reason);
        }
    }

    /// <summary>
    /// Event handler for the ActiveX control OnFatalError event.
    /// </summary>
    this.controlConnectErrorHandler = _controlConnectErrorHandler;
    function _controlConnectErrorHandler(reason){
        log.info("[" + this.Id + "]:  RDPActiveXTermClient received connect error event from the ActiveX control for: " + this._hostURL + ", code: " + reason);
        // raise the OnConnectError event
        this._raiseEvent("OnConnectError", null);
    }

    /// <summary>
    /// Event handler for ActiveX control OnChannelReceivedData event called
    /// when data is received on a virtual channel.  Noop in base class.
    /// </summary>
    this.controlChannelRecvHandler = _controlChannelRecvHandler;
    function _controlChannelRecvHandler(chanName, data){
    }

    /// <summary>
    /// Event handler for ActiveX control OnAutoReconnecting event called
    /// when a disconnect has occurred.
    /// </summary>
    this.controlAutoReconnectingHandler = _controlAutoReconnectingHandler;
    function _controlAutoReconnectingHandler(disconnectReason, attemptCount){
        log.info("[" + this.Id + "]:  RDPActiveXTermClient received AutoReconnecting event from the ActiveX control for: " + this._hostURL + ", reason: " + disconnectReason + ", count: " + attemptCount);
        // raise the OnAutoReconnecting event
        this._raiseEvent("OnAutoReconnecting", null);
        // return autoReconnectContinueAutomatic (0)
        return 0;
    }

    /// <summary>
    /// Event handler for ActiveX control for OnReadyStateChange event called
    /// when the control loads. (used to initiate the connection instead of the
    /// call from URACoordinator since as of RDP 6.1 this is the only time the
    /// Connect method on the ActiveX can be called successfully without enabling
    /// the "Initialize and script Active X controls not marked as safe for
    /// scripting" setting in IE for the Internet Zone)
    /// </summary>
    this.controlReadyStateChangeHandler = _controlReadyStateChangeHandler;
    function _controlReadyStateChangeHandler(control){
        if (control.readyState == 4){
            this._control = control;
            this.connect(true);
        }
    }

    /// <summary>
    /// Method gets the ActiveX or Applet control of the TermClient depending upon what 
    /// ControlPlatform has been deployed.
    /// </summary>
    /// <return type="object">the internal control, if this control has not been properly
    /// initialized this method ***can return null***</return>
    this.getControl = _getControl;
    function _getControl(){
        return this._control;
    }

    /// <summary>
    /// Internal method to determine if the control is actively connected.
    /// It is unlikely that this method should be overridden.
    /// </summary>
    this._controlIsConnected = _controlIsConnected;
    function _controlIsConnected(){
        var ret;
        try {
            ret = this._control.Connected;
            log.debug("[" + this.Id + "]: Control get_Connected is " + (ret? "true" : "false"));
        }
        catch (e) {
            log.debug("[" + this.Id + "]: Control get_Connected threw an exception");
            ret = false;
        }
        return ret;
    }

    /// <summary>
    /// Public method to determine if the TermClient session is established.
    /// A deriving class will override this if its definition of what
    /// constitutes a session is broader than an active RDP connection.
    /// </summary>
    this.isConnected = _isConnected;
    function _isConnected(){
        var ret;
        ret = this._controlIsConnected();
        log.info("[" + this.Id + "]: RDPActiveXTermClient.isConnected returning " + (ret? "true" : "false"));
        return ret;
    }

}
// register this instance with the TermClientFactory
termClientFactory.registerTermClient(ControlPlatform.ActiveX, TermClientType.RDP, "RDPActiveXTermClient");


/**********************************************************************
   $Author: greynold $
   $Date: 2008/02/26 22:01:12 $
   $Revision: 1.25 $


   Copyright 2001 - 2007. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/

/// <summary>
/// Implementation class for the RDP Applet TermClient object.  Unlike other
/// TermClients, this client has different implementations based on the 
/// OS of the client.  For Mac OSX, the implementation leverages the MS 
/// native RDC control.  All other platforms use the Propero RDP applet.
/// </summary>
/// <param name="id" type="string">the id of the TermClient instance</param>
function RDPJavaTermClient(id){
    // change the implementation based on the matching of the string 
    // in the user agent
    if(navigator.userAgent.toLowerCase().indexOf('mac os x') != -1){
        this.base = RDPJavaTermClientMac;
        this.base(id);
    } else {
        this.base = RDPJavaTermClientDefault;
        this.base(id);
    }
}

// register this instance with the TermClientFactory
termClientFactory.registerTermClient(ControlPlatform.Applet, TermClientType.RDP, "RDPJavaTermClient");

//**********************************************************************
/// <summary>
/// Implementation class for the RDP Applet TermClient object for default systems.
/// </summary>
/// <param name="id" type="string">the id of the TermClient instance</param>
function RDPJavaTermClientDefault(id){
/// region : inheritance --------------------------------------------
    this.base = TermClient;
    this.base(id);
    log.info("[" + id + "]:  RDPJavaTermClientDefault object created.");

/// region : private fields -----------------------------------------
    this._ctlSuffix = "_ax";

/// region : private fields -----------------------------------------
    this._termClientType = TermClientType.RDP;
    this._control = null; // holds a reference to the HTML element
    this._connectCount = 25; // counter for the number of permissable connection attempts

/// region : Properties ---------------------------------------------

    /// <summary>
    /// Gets/sets the Protocol for this object.
    /// </summary>
    this.Protocol = TermClientProtocol.RDP;

    /// <summary>
    /// Gets/sets the ControlPlatform for this object.
    /// </summary>
    this.Platform = ControlPlatform.Applet;

    /// <summary>
    /// Gets/sets the TermClientType for this object.
    /// </summary>
    this.TermClientType = TermClientType.RDP;

/// region : Methods ------------------------------------------------

    /// <summary>
    /// Method handles any initialization needed for the control before the connect() method 
    /// is called.  Not all controls will implement the init() method therefore this is not 
    /// a "virtual" method, just an empty stub that must be overridden for any effect to occur.
    /// </summary>
    /// <param name="args" type="object">initialization arguments, this is dependent upon implementation</param>
    this.init = _init;
    function _init(args){
        // no noop call here, if a control does not override, fail silently.
        return;
    }

    /// <summary>
    /// Wait for the applet to be initialized and started,
    /// then call _controlConnect() to instruct the applet to connect,
    /// then asynchronously call _verifyConnection() to ensure the
    /// RDP connection is established.
    /// </summary>
    this.connect = _connect;
    function _connect(){        
        // create a counter for the number of connection attempts
        if(typeof(this._connectionAttempt) == "undefined"){
            this._connectionAttempt = 0;
        }

        try
        {
            // find our control and bind to it
            this._control = this.Element.getElementById(this.Id + this._ctlSuffix);
            if(this._control == null){
                log.error("[" + this.Id + "]:  RDPJavaTermClientDefault unable to find rendered object tag in document.");
                throw this._newError("No download error.");
            }
            log.debug("[" + this.Id + "]:  RDPJavaTermClientDefault._control = " + this._control.tagName);

            try
            {
                // the isStarted method is a simple boolean test, the results of which don't matter 
                // at this point, to verify that the control has been loaded properly this method just 
                // needs to return a value and not throw an exception because the method is not supported.
                if(this._control.isStarted()){
                    log.info("[" + this.Id + "]:  RDPJavaTermClientDefault preparing to connect.");
                    this._hostURL = this.Protocol + "://" + this.HostAddress + ":" + this.HostPort;
                    this._controlConnect();
                    this._setTimeout(this.Id + "._verifyConnection()", 1000);
                } else {
                    throw this._newError("Applet isStarted is false");
                }
            }
            catch (ex)
            {
                log.info("[" + this.Id + "]:  RDPJavaTermClientDefault attempting connection:  " + this._connectionAttempt);
                if(this._connectionAttempt < this._connectCount){
                    this._connectionAttempt++;
                    this._setTimeout(this.Id + ".connect()", 1000);
                } else {
                    this._raiseEvent("OnLoadError", null);
                }                
            }
        }
        catch (e)
        {
            if(e.message == "No download error."){
                log.fatal("[" + this.Id + "]:  RDPJavaTermClientDefault control unable to initialize due to download or installation error.");
            } else {
                log.fatal("[" + this.Id + "]:  RDPJavaTermClientDefault control suffered a fatal initialization error: " + e.message);
            }
            this._raiseEvent("OnConnectError", null);
        }
    }

    /// <summary>
    /// Instruct the applet to connect.
    /// Noop in base class because the applet automatically connects on start.
    /// </summary>
    this._controlConnect = _controlConnect;
    function _controlConnect(){
    }

    /// <summary>
    /// Method invoked once the applet is instructed to connect to poll
    /// _controlIsConnected() to determine when the applet connects.
    /// Invokes controlConnectHandler() or controlConnectErrorHandler().
    /// </summary>
    this._verifyConnection = _verifyConnection;
    function _verifyConnection(){
        if(typeof(this._verifyConnectionAttempt) == "undefined"){
            this._verifyConnectionAttempt = 0;
        }
        if(this._controlIsConnected()){
            // the control is connected so begin the connection polling process
            this._setInterval(this.Id + "._pollConnection()", 1000);
            // fake that there was a control connection event by calling the handler
            this.controlConnectHandler();
        } else {
            if(this._verifyConnectionAttempt < this._connectCount){
                this._verifyConnectionAttempt++;
                log.info("[" + this.Id + "]:  RDPJavaTermClientDefault attempting connection verification:  " + this._verifyConnectionAttempt);
                this._setTimeout(this.Id + "._verifyConnection()", 1000);
            } else {
                // fake that there was a control connection error by calling the handler
                this.controlConnectErrorHandler();
            }
        }
    }

    /// <summary>
    /// Method polled on interval once the RDP connection is established.
    /// In the base class, this method delegates to _checkControlConnected().
    /// </summary>
    this._pollConnection = _pollConnection;
    function _pollConnection(){
        this._checkControlConnected();
    }

    /// <summary>
    /// Calls _controlIsConnected() to determine when the applet disconnects.
    /// Invokes controlDisconnectHandler().
    /// </summary>
    this._checkControlConnected = _checkControlConnected;
    function _checkControlConnected(){
        if(!this._controlIsConnected()){
            // stop polling the connection now
            this._cancelInterval();
            // fake that there was a control disconnection by calling the handler
            this.controlDisconnectHandler();
        }
    }

    /// <summary>
    /// Method tells the TermClient to attempt to disconnect from the remote session.
    /// </summary>
    this.disconnect = _disconnect;
    function _disconnect(args) {
        try{
            this._control.disconnect();
            log.info("[" + this.Id + "]:  RDPJavaTermClientDefault successfully disconnected from: " + this._hostURL);
        } catch (e){
            log.error("[" + this.Id + "]:  RDPJavaTermClientDefault suffered an error attempting to disconnect: " + e.message);
        }
    }

    /// <summary>
    /// Method renders the TermClient's HTML to the target frame's document.  The method 
    /// of render varies for each implementation.
    /// </summary>
    this.renderHtml = _renderHtml;
    function _renderHtml() {
        var ctlid = this.Id + this._ctlSuffix;
        // alternately 'archive="/URA/URA/lib/properJavaRDP13.jar"' +
        var output = "";
        return output = '<applet id="' + ctlid + '"' + 
                    'code="net.propero.rdp.applet.RdpPanelApplet.class" ' + 
                    'archive="' + appPath + '/URA/lib/properJavaRDP.jar"' + 
                    'width="' + this.Width + '" height="' + this.Height + '"' + 
                    'style="padding:0px;margin:0px;" >' + 
                    '<param name="-g" value="' + this.Width + 'x' + this.Height + '">' + 
                    '<param name="-h" value="' + this.HostAddress + ':' + this.HostPort + '">' + 
                    '<param name="-l" value="INFO">' +  
                    '<param name="-m" value="en-us">' + 
                    ((this.Username != "")? '<param name="-u" value="' + this.Username + '" />' : '' ) + 
                    ((this.Password != "")? '<param name="-p" value="' + this.Password + '" />' : '') + 
                    '<param name="connect" value="true" />' +
                '</applet>';
    }

    /// <summary>
    /// Method to send Ctrl+Alt+Delete to the TermClient control
    /// </summary>
    this.sendCtrlAltDelete = _sendCtrlAltDelete;
    function _sendCtrlAltDelete(){
        alert("To send CTRL+ALT+DEL use the following key combination:\n\tCTRL+ALT+END");
    }

    /// <summary>
    /// Method to retrieve the key commands to send Ctrl+Alt+Delete to the TermClient control.
    /// </summary>
    this.getCADCommand = _getCADCommand;
    function _getCADCommand(){
        return "CTRL+ALT+END";
    }

    /// <summary>
    /// This method called by _verifyConnection() to fake asynchronous applet events
    /// </summary>
    this.controlConnectHandler = _controlConnectHandler;
    function _controlConnectHandler(){
        log.info("[" + this.Id + "]:  RDPJavaTermClientDefault successfully connected to: " + this._hostURL);
        // raise the OnConnect event
        this._raiseEvent("OnConnect", null);
    }

    /// <summary>
    /// This method called by _checkControlConnected() to fake asynchronous applet events
    /// </summary>
    this.controlDisconnectHandler = _controlDisconnectHandler;
    function _controlDisconnectHandler(){
        log.info("[" + this.Id + "]:  RDPJavaTermClientDefault successfully disconnected from: " + this._hostURL);
        // raise the OnDisconnect event
        this._raiseEvent("OnDisconnect", null);
    }

    /// <summary>
    /// This method called by _verifyConnection() to fake asynchronous applet events
    /// </summary>
    this.controlConnectErrorHandler = _controlConnectErrorHandler;
    function _controlConnectErrorHandler(){
        log.info("[" + this.Id + "]:  RDPJavaTermClientDefault failed to connect to: " + this._hostURL);
        // raise the OnConnectError event
        this._raiseEvent("OnConnectError", null);
    }

    /// <summary>
    /// Method gets the ActiveX or Applet control of the TermClient depending upon what 
    /// ControlPlatform has been deployed.
    /// </summary>
    /// <return type="object">the internal control, if this control has not been properly
    /// initialized this method ***can return null***</return>
    this.getControl = _getControl;
    function _getControl(){
        return this._control;
    }

    /// <summary>
    /// Internal method to determine if the control is actively connected.
    /// Used by polling to determine when the RDP connection is broken.
    /// It is unlikely that this method should be overridden.
    /// </summary>
    this._controlIsConnected = _controlIsConnected;
    function _controlIsConnected(){
        var ret;
        try {
            ret = this._control.isConnected();
            log.debug("[" + this.Id + "]: Applet isConnected is " + (ret? "true" : "false"));
        }
        catch (e) {
            log.debug("[" + this.Id + "]: Applet isConnected threw an exception");
            ret = false;
        }
        return ret;
    }

    /// <summary>
    /// Public method to determine if the TermClient session is established.
    /// A deriving class will override this if its definition of what
    /// constitutes a session is broader than an active RDP connection.
    /// </summary>
    this.isConnected = _isConnected;
    function _isConnected(){
        var ret;
        ret = this._controlIsConnected();
        log.info("[" + this.Id + "]:  RDPJavaTermClientDefault.isConnected returning " + (ret? "true" : "false"));
        return ret;
    }

}


//**********************************************************************
/// <summary>
/// Implementation class for the RDP Applet TermClient object for the Mac OSX system.
/// </summary>
/// <param name="id" type="string">the id of the TermClient instance</param>
function RDPJavaTermClientMac(id){
/// region : inheritance --------------------------------------------
    this.base = TermClient;
    this.base(id);
    log.info("[" + id + "]:  RDPJavaTermClientMac object created.");

/// region : private fields -----------------------------------------
    this._ctlSuffix = "_ax"; // the suffix applied to the HTML element Id
    this._frmSuffix = "_frm"; // the suffix applied to the IFrame element Id
    this._protocol = "rdp://"; // the protocol scheme for this implementation
    this._connection = null; // holds a reference to the connection object
    this._gatewayName = "/HTGateway/"; // default URL bit for the gateway server
    this._termClientType = TermClientType.VmcConsole;
    this._control = null; // holds a reference to the HTML element
    this._frame = null; // holes a reference to the IFrame element
    this._connectCount = 0; // counter for the number of permissable connection attempts
    this._successfulConnect = false; // switch for indicating when the control has successfully connected
    this._fileProxy = "ConsoleProxy.aspx"; // proxy file for downloading console connection files
    this._fileName = "MacRDP.aspx"; // base .aspx file name targeted by the control
    this._targetRdp = ""; // target url for the xvm file
    this._verifyCount = 0; // counter for the number of connection verification attempts    
    this._hostURL = ""; // holds the complete URL for the host
    this._gatewayURL = ""; // holds the complete URL for the gateway
    this._hasDownloaded = false; // boolean flag set to true once the .xvm has been downloaded

/// region : Properties ---------------------------------------------

    /// <summary>
    /// Gets/sets the name of the class that handles the upstream encoding.  This must be one of the following
    /// values:  "" or a comma delimited list of:  "OctetStreamUpHandler", "MultipartFormUpHandler" , "Base64UpHandler"
    /// </summary>   
    this.UpstreamHandler = "com.surgient.localproxy.connections.http.OctetStreamHandler$UpHandler,com.surgient.localproxy.connections.http.MultipartFormUpHandler,com.surgient.localproxy.connections.http.Base64Handler$UpHandler";
    
    /// <summary>
    /// Gets/sets the name of the class that handles the downstream encoding.  This must be one of the following
    /// values:  "" or a comma delimited list of:  "OctetStreamDnHandler", "Base64DnHandler"
    /// </summary>  
    this.DownstreamHandler = "com.surgient.localproxy.connections.http.OctetStreamHandler$DnHandler,com.surgient.localproxy.connections.http.Base64Handler$DnHandler";

    /// <summary>
    /// Gets/sets the Protocol for this object.
    /// </summary>
    this.Protocol = TermClientProtocol.VmcConsole;

    /// <summary>
    /// Gets/sets the ControlPlatform for this object.
    /// </summary>
    this.Platform = ControlPlatform.Applet;

    /// <summary>
    /// Gets/sets the TermClientType for this object.
    /// </summary>
    this.TermClientType = TermClientType.VmcConsole;

    /// <summary>
    /// Gets/sets the host IP address for this object.
    /// </summary>
    this.HostAddress = "";

    /// <summary>
    /// Gets/sets the destination port for this object.
    /// </summary>
    this.HostPort = "";

    /// <summary>
    /// Gets/sets the vm name for this object.
    /// </summary>
    this.VmName = "";

    /// <summary>
    /// Gets/sets the width setting for this object.
    /// </summary>
    this.Width = 0;

    /// <summary>
    /// Gets/sets the height setting for this object.
    /// </summary>
    this.Height = 0;

    /// <summary>
    /// Gets/sets the HTML element reference this TermClient instance is loaded in.
    /// </summary>
    this.Element = null;

    /// <summary>
    /// Gets/sets the Username to use when connecting to this TermClient host.
    /// </summary>
    this.Username = "";

    /// <summary>
    /// Gets/sets the Password to use when connecting to this TermClient host.
    /// </summary>
    this.Password = "";

    /// <summary>
    /// Gets/sets the Username required to authenticate via the TermClient's protocol.
    /// </summary>
    this.ProtocolUsername = "";

    /// <summary>
    /// Gets/sets the Password required to authenticate via the TermClient's protocol.
    /// </summary>
    this.ProtocolPassword = "";

    /// <summary>
    /// Gets/sets the Password required to authenticate on the vm's Host.
    /// </summary>
    this.HostUsername = "";

    /// <summary>
    /// Gets/sets the Password required to authenticate on the vm's Host.
    /// </summary>
    this.HostPassword = "";

/// region : Methods ------------------------------------------------

    /// <summary>
    /// Method handles any initialization needed for the control before the connect() method 
    /// is called.  Not all controls will implement the init() method therefore this is not 
    /// a "virtual" method, just an empty stub that must be overridden for any effect to occur.
    /// </summary>
    /// <param name="args" type="object">initialization arguments, this is dependent upon implementation</param>
    this.init = _init;
    function _init(args){
        // no noop call here, if a control does not override, fail silently.
        return;
    }

        /// <summary>
    /// Method renders the TermClient's HTML to the target frame's document.  The method 
    /// of render varies for each implementation.
    /// </summary>
    this.renderHtml = _renderHtml;
    function _renderHtml() {
        var ctlid = this.Id + this._ctlSuffix;
        return '<applet id="' + ctlid + '" code="com.surgient.localproxy.applet.ProxyApplet.class" archive="' + appPath + '/URA/lib/LocalProxyApplet.jar"' + 
            ' height="0" width="0">' + 
            '<param name="logLevel" value="5" />' + 
            '<param name="cabbase" value="' + appPath + '/URA/lib/LocalProxyApplet11.cab" />' + 
            '</applet>' + 
            '<br/><br/><br/><br/><center><div style="width:60%;font-family:Verdana,Trebuchet,Arial,Helvetica;font-size:12px;">' + 
            'The requested Virtual Machine connection will open in another application.  ' + 
            'You must accept the pop-up window, download the file and open it in order to complete the connection.  ' + 
            'Once you have connected, <em>do not</em> close this window or your connection will be terminated.' + 
            '</div></center>';
    }

    /// <summary>
    /// Method tells the TunnelConfig to attempt to start the remote session. Raises 
    /// an OnConnect event.
    /// </summary>
    this.connect = _connect;
    function _connect(){
        try{
            // get the ref to the HTML element
            if(this._control == null){
                this._control = this.Element.getElementById(this.Id + this._ctlSuffix);
                if(this._control == null){
                    log.error("[" + this.Id + "]:  RDPJavaTermClientMac unable to find rendered object tag in document.");
                    throw this._newError("Unable to target control HTML tag");
                }
            }
            log.debug("[" + this.Id + "]:  RDPJavaTermClientMac._control = " + this._control.tagName);
            
            try
            {
            	// the isStarted method is a simple boolean test, the results of which don't matter 
                // at this point, to verify that the control has been loaded properly this method just 
                // needs to return a value and not throw an exception because the method is not supported.
                if(this._control.isStarted()){
                    log.info("[" + this.Id + "]:  RDPJavaTermClientMac attempting to connect to host: " + this.HostAddress + ":" + this.HostPort);
                    this._connectCount = 0;

                    // create the connection object using the destination address
                    if(this.HostAddress != ""){
                        if(this.HostPort != ""){
                            this._hostURL = this.Protocol + "://" + this.HostAddress + ":" + this.HostPort;
                        } else {
                            this._hostURL = this.Protocol + "://" + this.HostAddress;
                        }
                        log.info("[" + this.Id + "]:  RDPJavaTermClientMac establishing connection to host: " + this._hostURL);
                        this._connection = this._control.newConnection(this._hostURL);
                    } else {
                        log.error("[" + this.Id + "]:  RDPJavaTermClientMac.HostAddress property is invalid and cannot be connected.");
                        throw this._newError("HostAddress property is invalid.");
                    }

                    // set the connection classname
                    this._connection.getPropertyBag().setProperty("ProxyConnection.connectionClasses", "com.surgient.localproxy.connections.socket.SocketConnection");

                    // now try to start the connection
                    this._connection.asyncStart();

                    // finally set up a callback to verify the connection was made
                    this._setTimeout(this.Id + "._verifyConnection()", 1000);                    
                } else {
                    log.error("[" + this.Id + "]: LocalProxy applet does not show isStarted method.");
                    throw this._newError("No isStarted method");
                }
            }
            catch (ex)
            {
                log.debug("[" + this.Id + "]:  RDPJavaTermClientMac control error while trying to start: " + ex.message);
                // if the control has tried to connect 25 times, it's not going to be 
                // successful so message that up to a handler
                if(this._connectCount < 25){
                    // the ActiveX control is not yet ready, so re-call this function after a set timeout
                    this._setTimeout(this.Id + ".connect()", 1000);
                    this._connectCount++;
                } else {
                    log.fatal("[" + this.Id + "]:  RDPJavaTermClientMac control unable to initialize due to a download or installation error.");
                    // raise an OnLoadError event
                    this._raiseEvent("OnLoadError", null);
                }
            }
        } catch(e){
            log.fatal("[" + this.Id + "]:  RDPJavaTermClientMac suffered a fatal error during the connect() method: " + e.message);
            this.connectError(e);
            return;
        }
    }

    /// <summary>
    /// Private method to verify the TunnelConfig's connection before raising the OnConnect event.
    /// </summary>    
    this._verifyConnection = _verifyConnection;
    function _verifyConnection(){
        try
        {
            if(this._connection == null){
                log.error("[" + this.Id + "]:  RDPJavaTermClientMac control's Connection object was uninstantiated.");
                throw this._newError("Connection was uninstantiated in ActiveX control.");
            }
            if(this.isConnected()){
                log.info("[" + this.Id + "]:  RDPJavaTermClientMac successfully connected to host: " + this._hostURL);
                if(!this._hasDownloaded){
                    this._constrainSize();
                    // set the global config settings
                    var colorDepth;
                    switch(TerminalClientSettings.ColorDepth){
                        case 8 : 
                            colorDepth = 0;
                            break;
                        case 16 : 
                            colorDepth = 1;
                            break;
                        default :
                            colorDepth = 2;
                    }
                    this._targetRdp = appPath + "/" + this._fileName + 
                        "?connectionString=" + this.getDestinationIPAddress() + 
                        ":" + this.getDestinationPort() + 
                        "&session=" + this.Id + 
                        "&userName=" + this.Username + 
                        "&password=" + this.Password + 
                        "&width=" + this.Width + 
                        "&height=" + this.Height + 
                        "&colorDepth=" + colorDepth;
                    var encodedRdp = this._urlEncode(this._targetRdp);
                    var proxyPath = appPath + "/" + this._fileProxy + "?path=" + encodedRdp;

                    var win = window.open(proxyPath, "SurgientDownloads", "width=480,height=200");
                    this._hasDownloaded = true;
                }
                // begin the client connection polling cycle to see if it responds
                this._setTimeout(this.Id + "._verifyClientConnection()", 1000);
            } else {
                if(this._verifyCount < 20){
                    this._verifyCount++;
                    this._setTimeout(this.Id + "._verifyConnection()", 1000);
                } else {
                    log.error("[" + this.Id + "]:  RDPJavaTermClientMac was unable to verify to host: " + this._hostURL);
                    throw this._newError("RDPJavaTermClientMac connection verification failed.");
                }
            }
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  RDPJavaTermClientMac suffered a fatal error attempting to verify the connection: " + e.message);
            this.connectError(e);
            return;
        }
    }    

    /// <summary>
    /// Private method to verify that the external client has connected through this TermClient
    /// </summary>  
    this._verifyClientConnection = _verifyClientConnection;
    function _verifyClientConnection(){
        try
        {
            if(this._connection == null){
                log.error("[" + this.Id + "]:  RDPJavaTermClientMac control's Connection object was uninstantiated.");
                throw this._newError("Connection was uninstantiated in ActiveX control.");
            }
            if(this.isConnected() && this._connection.getConnectionCount() > 0){
                // prevent any more connections to this object
                //this._connection.Stop();
                // begin cyclical polling of the connection to make sure things are working
                this._setTimeout(this.Id + "._pollConnection()", 1500);
                this._raiseEvent("OnConnect", null);
            } else {
                if(this._verifyCount < 20){
                    this._verifyCount++;
                    this._setTimeout(this.Id + "._verifyClientConnection()", 2000);
                } else {
                    throw this._newError("RDPJavaTermClientMac client connection verification failed.");
                }
            }
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  RDPJavaTermClientMac suffered a fatal error attempting to verify the client connection: " + e.message);
            this.connectError(e);
            return;
        }
    }
    
    /// <summary>
    /// Private method that polls the control every second to determine if the 
    /// connection is still viable.  If not, it raises the OnDisconnect event.
    /// </summary>
    this._pollConnection = _pollConnection;
    function _pollConnection(){
        if(this.isConnected() && this._connection.getConnectionCount() > 0){
            this._setTimeout(this.Id + "._pollConnection()", 1000);
        } else {
            log.info("[" + this.Id + "]:  RDPJavaTermClientMac connection poll returned a disconnected state.");
            this._connection.asyncStop();
            this._setTimeout(this.Id + '._raiseEvent("OnDisconnect", null)', 2000);
        }
    }

    /// <summary>
    /// Method tells the TunnelConfig to attempt to disconnect.
    /// </summary>
    this.disconnect = _disconnect;
    function _disconnect(args) {
        // calls the Abort() method on the connection object
        this._connection.asyncStop();
        log.info("[" + this.Id + "]:  RDPJavaTermClientMac successfully disconnected from host: " + this._hostURL + " via gateway: " + this._gatewayURL);
        // raise the OnDisconnect event, passing the results up the chain
        this._raiseEvent("OnDisconnect", args);
    }

    /// <summary>
    /// Method called by the TunnelConfig instance when a connection error has occurred.  Raises 
    /// an OnConnectError event.
    /// </summary>
    this.connectError = _connectError;
    function _connectError(error) {
        log.error("[" + this.Id + "]:  RDPJavaTermClientMac failed to connect to host: " + this._hostURL + " via gateway: " + this._gatewayURL);
        // raise the OnConnectError event
        this._raiseEvent("OnConnectError", error.message);
    }

    /// <summary>
    /// Checks the applet for whether it is connected.
    /// True/False indicates connection state; throws on connection error.
    /// </summary>
    this._checkConnected = _checkConnected;
    function _checkConnected(){
        try {
            var ret = this._connection.isStartedOk();
            if (ret >= 0) {
                return (ret > 0)? true : false;
            }
        }
        catch (e) {
            log.warn("[" + this.Id + "]:  RDPJavaTermClientMac._checkConnected cannot verify applet isStartedOk()");
            return false;
        }
        // isStartedOk() returned error (<0)
        var errorMessage;
        try {
            errorMessage = this._connection.getLastError().getMessage();
        }
        catch (e) {
            errorMessage = "applet isStartedOk() returned error";
        }
        log.warn("[" + this.Id + "]:  RDPJavaTermClientMac._checkConnected: applet error: " + errorMessage);
        throw this._newError(errorMessage);
    }

    /// <summary>
    /// Method determines if the control is actually connected or not, helpful for polling
    /// exercises and error checking in the URACoordinators.
    /// </summary>
    this.isConnected = _isConnected;
    function _isConnected(){
        try
        {
            if (this._checkConnected()) {
                log.info("[" + this.Id + "]:  RDPJavaTermClientMac.isConnected returned: true");
                return true;
            }
            else {
                log.info("[" + this.Id + "]:  RDPJavaTermClientMac.isConnected returned: false");
                return false;
            }
        }
        catch (e)
        {
            log.info("[" + this.Id + "]:  RDPJavaTermClientMac.isConnected returned: false");
            return false;
        }
    }

    /// <summary>
    /// Method gets the ActiveX or Applet control of the TermClient depending upon what 
    /// ControlPlatform has been deployed.
    /// </summary>
    /// <return type="object">the internal control, if this control has not been properly
    /// initialized this method ***can return null***</return>
    this.getControl = _getControl;
    function _getControl(){
        return this._control;
    }

    /// <summary>
    /// Gets the local IPAddress of the TunnelConfig.
    /// </summary>
    /// <return type="string">the local IPAddress of the TunnelConfig</return>
    this.getDestinationIPAddress = _getDestinationIPAddress;
    function _getDestinationIPAddress() {
        try
        {
            var addr = this._connection.getLocalAddress();
            if (addr == null) {
                var ex = this._connection.getLastError();
                if (ex != null) {
                    throw this._newError("applet getLocalAddress() error: " + ex.getMessage());
                }
                else {
                    throw this._newError("applet getLocalAddress() returned null");
                }
            }
            return addr.getHostAddress();
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  RDPJavaTermClientMac.getDestinationIPAddress() suffered a fatal error: " + e.message);
            throw this._newError("RDPJavaTermClientMac connection does not return address: " + e.message);
        }
    }

    /// <summary>
    /// Gets the local Port of the TunnelConfig.
    /// </summary>
    this.getDestinationPort = _getDestinationPort;
    function _getDestinationPort() {
        try
        {
            var port = this._connection.getLocalPort();
            if (port == 0) {
                var ex = this._connection.getLastError();
                if (ex != null) {
                    throw this._newError("applet getLocalPort() error: " + ex.getMessage());
                }
                else {
                    throw this._newError("applet getLocalPort() returned 0");
                }
            }
            return port;
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  RDPJavaTermClientMac.getDestinationPort() suffered a fatal error: " + e.message);
            throw this._newError("RDPJavaTermClientMac connection does not return port: " + e.message);
        }
    }

    /// <summary>
    /// Method to send Ctrl+Alt+Delete to the TermClient control
    /// </summary>
    this.sendCtrlAltDelete = _sendCtrlAltDelete;
    function _sendCtrlAltDelete(){
        alert("You must use the VMware client to send keys to the virtual machine.");
    }

    /// <summary>
    /// Method to retrieve the key commands to send Ctrl+Alt+Delete to the TermClient control.
    /// </summary>
    this.getCADCommand = _getCADCommand;
    function _getCADCommand(){
        // send null because the key command is supported by the control
        return null;
    }

    /// <summary>
    /// Method encodes a plaintext string into a URL safe format
    /// </summary>
    /// <param type="string" name="plaintext">the text to encode</param>
    /// <return type="string">the urlencoded string</return>
    this._urlEncode = _urlEncode;
    function _urlEncode(plaintext)
    {
        var safechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_.!~*'()";
        var HEX = "0123456789ABCDEF";
        var encoded = "";
        for (var i = 0; i < plaintext.length; i++ ) {
            var ch = plaintext.charAt(i);
            if (ch == " ") {
                encoded += "+";
            } else if (safechars.indexOf(ch) != -1) {
                encoded += ch;
            } else {
                var charCode = ch.charCodeAt(0);
                if (charCode > 255) {
                    encoded += "+";
                } else {
                    encoded += "%";
                    encoded += HEX.charAt((charCode >> 4) & 0xF);
                    encoded += HEX.charAt(charCode & 0xF);
                }
            }
        }
        return encoded;
    }

    /// <summary>
    /// Method limits the size of this control to prevent errors.
    /// </summary>
    this._constrainSize = _constrainSize;
    function _constrainSize(){
        if(this.Width > 1600){
            log.info("[" + this.Id + "]:  RDPJavaTermClientMac constraining width to: 1600px");
            this.Width = 1600;
        }
        if(this.Height > 1200){
            log.info("[" + this.Id + "]:  RDPJavaTermClientMac constraining height to: 1200px");
            this.Height = 1200;
        }
    }
}


/**********************************************************************
   $Author: csanford $
   $Date: 2008/04/04 21:13:50 $
   $Revision: 1.9 $


   Copyright 2001 - 2007. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/

/// <summary>
/// Implementation class for the RDPShadowing ActiveX TermClient object.
/// </summary>
/// <param name="id" type="string">the id of the TermClient instance</param>
function RDPShadowingActiveXTermClient(id){
/// region : inheritance --------------------------------------------
    this.base = RDPActiveXTermClient;
    this.base(id);
    log.info("[" + id + "]:  RDPShadowingActiveXTermClient object created.");

/// region : private fields -----------------------------------------
    this._ctlSuffix = "_ax";
    this._termClientType = TermClientType.RDPShadowing;
    this._isDisconnected = false;
    this._shadowProtoVersion = 1;
    this._shadowCommandChannel = "srdpsdw";
    this._startShadowingAttempt = 0;
    this._countSinceLastPing = 0;
    this._isShadowing = false;

/// region : Properties ---------------------------------------------
    /// <summary>
    /// Gets/sets the TermClientType for this object.
    /// </summary>
    this.TermClientType = TermClientType.RDPShadowing;

/// region : Methods ------------------------------------------------

    /// <summary>
    /// Create the RDP virtual channel on which to send shadowing instructions
    /// and connect the control to the server.
    /// </summary>
    this._controlConnect = _controlConnect;
    function _controlConnect(){
        log.info("[" + this.Id + "]:  RDPShadowingActiveXTermClient preparing to connect.");
        this._control.DesktopWidth = this.Width;
        this._control.DesktopHeight = this.Height;
        this._control.Server = this.HostAddress;
        this._control.AdvancedSettings2.RDPPort = this.HostPort;
        this._control.Domain = "";
        this._control.UserName = this.Username;
        this._control.AdvancedSettings2.ClearTextPassword = this.Password;
        this._control.CreateVirtualChannels(this._shadowCommandChannel);
        // set the global config settings
        var colorDepth;
        switch(TerminalClientSettings.ColorDepth){
            case 8 : 
                colorDepth = 8;
                break;
            case 16 : 
                colorDepth = 16;
                break;
            default :
                colorDepth = 24;
        }
        this._control.ColorDepth = colorDepth;
        //this._control = TerminalClientSettings.EnableSound // not supported
        this._control.FullScreen = TerminalClientSettings.EnableFullScreen;
        //this._control = TerminalClientSettings.EnableDriveMapping // not supported
        this._control.Connect();
    }

    /// <summary>
    /// Raises OnConnect event if not already raised or disconnected
    /// OnConnect for shadowing is raised when shadowing is established.
    /// </summary>
    this._raiseConnect = _raiseConnect;
    function _raiseConnect(reason){
        if (!this._isShadowing && !this._isDisconnected) {
            log.info("[" + this.Id + "]: RDPShadowingActiveXTermClient " + reason + " -> OnConnect");
            this._isShadowing = true;
            this._raiseEvent("OnConnect", null);
        }
        else {
            log.debug("[" + this.Id + "]: " + reason + ", but OnConnect/OnConnectError/OnDisconnect raised earlier -> (no event)");
        }
    }

    /// <summary>
    /// Raises OnDisconnect event if it has not already been raised.
    /// Raises OnConnectError event if OnConnect has not been raised.
    /// </summary>
    this._raiseDisconnect = _raiseDisconnect;
    function _raiseDisconnect(reason){
        // checks isShadowing for whether OnConnect has been raised.
        // checks isDisconnected for whether OnDisconnect was already raised.
        if (this._isShadowing && !this._isDisconnected) {
            log.info("[" + this.Id + "]: RDPShadowingActiveXTermClient " + reason + " -> OnDisconnect");
            this._hasConnected = false;
            this._isShadowing = false;
            this._isDisconnected = true;
            this._raiseEvent("OnDisconnect", null);
        }
        else if (!this._isDisconnected) {
            log.info("[" + this.Id + "]: RDPShadowingActiveXTermClient " + reason + " -> OnConnectError");
            this._hasConnected = false;
            this._isShadowing = false;
            this._isDisconnected = true;
            this._raiseEvent("OnConnectError", null);
        }
        else {
            log.debug("[" + this.Id + "]: " + reason + ", but OnConnectError/OnDisconnect raised earlier -> (no event)");
        }
    }

    /// <summary>
    /// Shows an error dialog and raises OnConnectError(Abort) to prevent
    /// the URACoordinator from trying to shadow again with the RDP applet.
    /// </summary>
    /// <remarks>
    /// This should only be used in the case when the RDP control connects
    /// to the server but fails to establish the shadowing session.
    /// Presumably this is because no session to be shadowed exists or because
    /// the image is not configured properly for shadowing.
    /// </remarks>
    this._raiseError = _raiseError;
    function _raiseError(reason){
        // checks hasConnected, isShadowing, isDisconnected just to be safe.
        // delegate to _raiseDisconnect if this assertion fails
        if (!this._hasConnected || this._isShadowing || this._isDisconnected) {
            log.warn("[" + this.Id + "]: ASSERT FAILED RDPShadowingActiveXTermClient cannot raise OnConnectError(Abort) after " + reason + ": connected=" + this._hasConnected + " shadowing=" + this._isShadowing + " disconnected=" + this._isDisconnected);
            this._raiseDisconnect(reason);
        }
        else {
            log.info("[" + this.Id + "]: RDPShadowingActiveXTermClient " + reason + " -> OnConnectError(Abort)");
            this._hasConnected = false;
            this._isShadowing = false;
            this._isDisconnected = true;
            alert('Failed to shadow the user session.  Possible causes of this error include:\r\n\r\n- The user is not currently connected via RDP\r\n- The permitted number of RDP sessions has been exceeded\r\n- The image is not configured to permit shadowing\r\n- The image is running an old version of the rdpshadowing.exe binary');
            this._raiseEvent("OnConnectError", TermClientConnectErrorArgs.Abort);
        }
    }

    /// <summary>
    /// Event handler for the ActiveX control OnDisconnected event.
    /// </summary>
    /// <remarks>
    /// Differs from base class by delegating to _raiseDisconnect().
    /// </remarks>
    this.controlDisconnectHandler = _controlDisconnectHandler;
    function _controlDisconnectHandler(reason){
        log.debug("[" + this.Id + "]:  RDPShadowingActiveXTermClient received disconnect event from the ActiveX control for: " + this._hostURL + ", code: " + reason);
        this._raiseDisconnect("got ActiveX OnDisconnected (" + reason + ")");
    }

    /// <summary>
    /// Event handler for the ActiveX control OnConnected event.
    /// </summary>
    /// <remarks>
    /// Does not raise OnConnect event.  Invokes startShadowing().
    /// </remarks>
    this.controlConnectHandler = _controlConnectHandler;
    function _controlConnectHandler(){
        log.info("[" + this.Id + "]:  RDPShadowingActiveXTermClient received connect event from the ActiveX control for: " + this._hostURL);
        this._hasConnected = true;
        // _isDisconnected is used to track whether OnDisconnect was raised
        // to prevent multiple OnDisconnect or OnConnectError events.
        // See _raiseDisconnect(reason)
        this._isDisconnected = false;
        // _isShadowing is "is actively shadowing"
        // See _raiseConnect(reason)
        this._isShadowing = false;
        // start shadowing and wait for rdpshadow confirmation.
        this._startShadowingAttempt = 0;
        this._setTimeout(this.Id + ".startShadowing()", 1000);
    }

    /// <summary>
    /// Event handler for ActiveX control OnChannelReceivedData event called
    /// when data is received on a virtual channel.
    /// </summary>
    this.controlChannelRecvHandler = _controlChannelRecvHandler;
    function _controlChannelRecvHandler(chanName, data){
        if (chanName == this._shadowCommandChannel) {
            log.debug("[" + this.Id + "]:  RDPShadowingActiveXTermClient received channel data: " + data);
            if((new String(data)).indexOf("ack") == 0){
                // confirms that the rdpshadow tool is 5.3+
                this._shadowProtoVersion = 2;
                // start timeout to count "seconds" since ping
                // see ping case below and _checkLastPing
                this._countSinceLastPing = 0;
                this._setTimeout(this.Id + "._checkLastPing()", 1000);
            }
            else if((new String(data)).indexOf("ok") == 0){
                this._raiseConnect("got 'ok' on virtual channel");
            }
            else if((new String(data)).indexOf("end") == 0){
                this._raiseDisconnect("got 'end' on virtual channel");
            }
            else if((new String(data)).indexOf("ping") == 0){
                // reset count while still getting pings
                this._countSinceLastPing = 0;
            }
            else if((new String(data)).indexOf("error:") == 0){
                this._raiseError("got '" + data + "' on virtual channel");
            }
            else {
                log.warn("[" + this.Id + "]: RDPShadowingActiveXTermClient received unexpected data on channel " + chanName);
            }
        }
    }

    /// <summary>
    /// Count the "seconds" since the last ping.
    /// </summary>
    /// <remarks>
    /// As it turns out (at least with w2k3sp1), when the shadow
    /// session is established, virtual channels established in the
    /// in the original session of the shadower are suspended.
    /// This means the shadower will not receive the "ok" confirmation.
    /// To counter this [security?] behavior, wait for the
    /// periodic "pings" to stop, and treat the silence as confirmation.
    /// </remarks>
    this._checkLastPing = _checkLastPing;
    function _checkLastPing() {
        var skip = (this._isShadowing || this._isDisconnected);
        if (!skip) {
            this._countSinceLastPing++;
            if (this._countSinceLastPing >= 5) {
                this._raiseConnect("~5 seconds since last 'ping'");
            }
            else {
                this._setTimeout(this.Id + "._checkLastPing()", 1000);
            }
        }
    }

    /// <summary>
    /// Sends a string on the RDP virtual channel that tells rdpshadow.exe
    /// listening on this channel inside the target system to start the
    /// shadowing session.
    /// </summary>
    this.startShadowing = _startShadowing;
    function _startShadowing(){        
        // data isn't buffered until the rdpshadow.exe tool is bound to the
        // virtual channel, so keep on sending the command for 20 seconds
        var skip = (this._isShadowing || this._isDisconnected);
        if(!skip && this._startShadowingAttempt < 10){
            log.debug("[" + this.Id + "]: RDPShadowingActiveXTermClient send command to start shadowing");
            try {
                this._control.SendOnVirtualChannel(this._shadowCommandChannel, "shadow-v2\r\n");
            }
            catch (e) {
                if (this._shadowProtoVersion < 2 && this._startShadowingAttempt > 0) {
                    // the rdpshadow.exe 5.2 (aka version 1) tool closes the
                    // channel after receiving the command to shadow.
                    // this leads to an exception here.  once caught, raise
                    // OnConnect now because 5.2 has no explicit ok/error
                    // regarding shadow session
                    this._raiseConnect("error sending on channel after previous success, assume ok");
                    return;
                }
            }
            this._startShadowingAttempt++;
            this._setTimeout(this.Id + ".startShadowing()", 2000);
        }
        else if(!skip){
            this._raiseError("no shadow session start after 10 attempts, assume error");
        }
    }

    /// <summary>
    /// For shadowing TermClient, returns whether connected to shadow session.
    /// </summary>
    this.isConnected = _isConnected;
    function _isConnected(){
        var ret = this._controlIsConnected() && this._isShadowing;
        log.info("[" + this.Id + "]: RDPShadowingActiveXTermClient.isConnected returning " + (ret? "true" : "false"));
        return ret;
    }
    

}
// register this instance with the TermClientFactory
termClientFactory.registerTermClient(ControlPlatform.ActiveX, TermClientType.RDPShadowing, "RDPShadowingActiveXTermClient");


/**********************************************************************
   $Author: csanford $
   $Date: 2008/04/04 21:13:40 $
   $Revision: 1.6 $


   Copyright 2001 - 2007. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/

/// <summary>
/// Implementation class for the RDPShadowing Applet TermClient object.
/// </summary>
/// <param name="id" type="string">the id of the TermClient instance</param>
function RDPShadowingJavaTermClient(id){
/// region : inheritance --------------------------------------------
    this.base = RDPJavaTermClient;
    this.base(id);
    log.info("[" + id + "]:  RDPShadowingJavaTermClient object created.");

/// region : private fields -----------------------------------------
    this._ctlSuffix = "_ax";
    this._termClientType = TermClientType.RDPShadowing;
    this._hasConnected = false;
    this._isDisconnected = false;
    this._shadowProtoVersion = 1;
    this._shadowCommandChannel = "srdpsdw";
    this._startShadowingAttempt = 0;
    this._countSinceLastPing = 0;
    this._isShadowing = false;

/// region : Properties ---------------------------------------------
    /// <summary>
    /// Gets/sets the TermClientType for this object.
    /// </summary>
    this.TermClientType = TermClientType.RDPShadowing;

/// region : Methods ------------------------------------------------

    /// <summary>
    /// Create the RDP virtual channel on which to send shadowing instructions
    /// and connect the applet to the server.
    /// </summary>
    this._controlConnect = _controlConnect;
    function _controlConnect(){
        log.info("[" + this.Id + "]:  RDPShadowingAppletTermClient preparing to connect.");
        this._control.createVirtualChannel(this._shadowCommandChannel);
        this._control.connect();
    }

    /// <summary>
    /// Method polled on interval once the RDP connection is established.
    /// Delegates to _checkVirtualChannel() and _checkControlConnected().
    /// </summary>
    this._pollConnection = _pollConnection;
    function _pollConnection(){
        // this is subtle: check the virtual first because it has
        // context as to why the control may be disconnecting.
        // then check whether disconnected.
        this._checkVirtualChannel();
        this._checkControlConnected();
    }

    /// <summary>
    /// Render the applet, but do not automatically connect.
    /// </summary>
    this.renderHtml = _renderHtml;
    function _renderHtml() {
        var ctlid = this.Id + this._ctlSuffix;
        // alternately 'archive="/URA/URA/lib/properJavaRDP13.jar"' +
        return '<applet id="' + ctlid + '"' + 
                    'code="net.propero.rdp.applet.RdpPanelApplet.class" ' + 
                    'archive="' + appPath + '/URA/lib/properJavaRDP.jar"' + 
                    'width="' + this.Width + '" height="' + this.Height + '"' + 
                    'style="padding:0px;margin:0px;" >' + 
                    '<param name="-g" value="' + this.Width + 'x' + this.Height + '">' + 
                    '<param name="-h" value="' + this.HostAddress + ':' + this.HostPort + '">' + 
                    '<param name="-l" value="INFO">' + 
                    '<param name="-m" value="en-us">' + 
                    '<param name="-u" value="' + this.Username + '" />' + 
                    '<param name="-p" value="' + this.Password + '" />' + 
                    '<param name="connect" value="false" />' + 
                '</applet>';
    }

    /// <summary>
    /// Raises OnConnect event if not already raised or disconnected
    /// OnConnect for shadowing is raised when shadowing is established.
    /// </summary>
    this._raiseConnect = _raiseConnect;
    function _raiseConnect(reason){
        if (!this._isShadowing && !this._isDisconnected) {
            log.info("[" + this.Id + "]: RDPShadowingJavaTermClient " + reason + " -> OnConnect");
            this._isShadowing = true;
            this._raiseEvent("OnConnect", null);
        }
        else {
            log.debug("[" + this.Id + "]: " + reason + ", but OnConnect/OnConnectError/OnDisconnect raised earlier -> (no event)");
        }
    }

    /// <summary>
    /// Raises OnDisconnect event if it has not already been raised.
    /// Raises OnConnectError event if OnConnect has not been raised.
    /// </summary>
    this._raiseDisconnect = _raiseDisconnect;
    function _raiseDisconnect(reason){
        // checks isShadowing for whether OnConnect has been raised.
        // checks isDisconnected for whether OnDisconnect was already raised.
        if (this._isShadowing && !this._isDisconnected) {
            log.info("[" + this.Id + "]: RDPShadowingJavaTermClient " + reason + " -> OnDisconnect");
            this._hasConnected = false;
            this._isShadowing = false;
            this._isDisconnected = true;
            this._raiseEvent("OnDisconnect", null);
        }
        else if (!this._isDisconnected) {
            log.info("[" + this.Id + "]: RDPShadowingJavaTermClient " + reason + " -> OnConnectError");
            this._hasConnected = false;
            this._isShadowing = false;
            this._isDisconnected = true;
            this._raiseEvent("OnConnectError", null);
        }
        else {
            log.debug("[" + this.Id + "]: " + reason + ", but OnConnectError/OnDisconnect raised earlier -> (no event)");
        }
    }

    /// <summary>
    /// Shows an error dialog and raises OnConnectError(Abort) to prevent
    /// the URACoordinator from trying to shadow again with RDP ActiveX.
    /// </summary>
    /// <remarks>
    /// This should only be used in the case when the RDP applet connects
    /// to the server but fails to establish the shadowing session.
    /// Presumably this is because no session to be shadowed exists or because
    /// the image is not configured properly for shadowing.
    /// </remarks>
    this._raiseError = _raiseError;
    function _raiseError(reason){
        // checks hasConnected, isShadowing, isDisconnected just to be safe.
        // delegate to _raiseDisconnect if this assertion fails
        if (!this._hasConnected || this._isShadowing || this._isDisconnected) {
            log.warn("[" + this.Id + "]: ASSERT FAILED RDPShadowingJavaTermClient cannot raise OnConnectError(Abort) after " + reason + ": connected=" + this._hasConnected + " shadowing=" + this._isShadowing + " disconnected=" + this._isDisconnected);
            this._raiseDisconnect(reason);
        }
        else {
            log.info("[" + this.Id + "]: RDPShadowingJavaTermClient " + reason + " -> OnConnectError(Abort)");
            this._hasConnected = false;
            this._isShadowing = false;
            this._isDisconnected = true;
            alert('Failed to shadow the user session.  Possible causes of this error include:\r\n\r\n- The user is not currently connected via RDP\r\n- The permitted number of RDP sessions has been exceeded\r\n- The image is not configured to permit shadowing\r\n- The image is running an old version of the rdpshadowing.exe binary');
            this._raiseEvent("OnConnectError", TermClientConnectErrorArgs.Abort);
        }
    }

    /// <summary>
    /// This method called by _checkControlConnected() to fake asynchronous applet events.
    /// </summary>
    /// <remarks>
    /// Differs from base class by delegating to _raiseDisconnect()
    /// </remarks>
    this.controlDisconnectHandler = _controlDisconnectHandler;
    function _controlDisconnectHandler(){
        log.debug("[" + this.Id + "]:  RDPShadowingJavaTermClient disconnect event for applet for: " + this._hostURL);
        this._raiseDisconnect("RDP connection terminated");
    }

    /// <summary>
    /// This method called by _verifyConnection() to fake asynchronous applet events.
    /// </summary>
    /// <remarks>
    /// Does not raise OnConnect event.  Invokes startShadowing().
    /// </remarks>
    this.controlConnectHandler = _controlConnectHandler;
    function _controlConnectHandler(){
        log.info("[" + this.Id + "]:  RDPShadowingJavaTermClient connect event for applet for: " + this._hostURL);
        this._hasConnected = true;
        // _isDisconnected is used to track whether OnDisconnect was raised
        // to prevent multiple OnDisconnect or OnConnectError events.
        // See _raiseDisconnect(reason)
        this._isDisconnected = false;
        // _isShadowing is "is actively shadowing"
        // See _raiseConnect(reason)
        this._isShadowing = false;
        // start shadowing and wait for rdpshadow confirmation.
        this._startShadowingAttempt = 0;
        this._setTimeout(this.Id + ".startShadowing()", 1000);
    }

    /// <summary>
    /// This method called by _checkVirtualChannel to fake asynchronous applet events.  Invoked when data is received on the RDP virtual channel.
    /// </summary>
    this.controlChannelRecvHandler = _controlChannelRecvHandler;
    function _controlChannelRecvHandler(chanName, data){
        if (chanName == this._shadowCommandChannel) {
            log.debug("[" + this.Id + "]:  RDPShadowingJavaTermClient received channel data: " + data);
            if((new String(data)).indexOf("ack") == 0){
                // confirms that the rdpshadow tool is 5.3+
                this._shadowProtoVersion = 2;
                // start timeout to count "seconds" since ping
                // see ping case below and _checkLastPing
                this._countSinceLastPing = 0;
                this._setTimeout(this.Id + "._checkLastPing()", 1000);
            }
            else if((new String(data)).indexOf("ok") == 0){
                this._raiseConnect("got 'ok' on virtual channel");
            }
            else if((new String(data)).indexOf("end") == 0){
                this._raiseDisconnect("got 'end' on virtual channel");
            }
            else if((new String(data)).indexOf("ping") == 0){
                // reset count while still getting pings
                this._countSinceLastPing = 0;
            }
            else if((new String(data)).indexOf("error:") == 0){
                this._raiseError("got '" + data + "' on virtual channel");
            }
            else {
                log.warn("[" + this.Id + "]: RDPShadowingJavaTermClient received unexpected data on channel " + chanName);
            }
        }
    }

    /// <summary>
    /// Reads from the RDP virtual channel.  Invokes controlChannelRecvHandler.
    /// </summary>
    this._checkVirtualChannel = _checkVirtualChannel;
    function _checkVirtualChannel(){
        var data = this._control.readFromVirtualChannel(this._shadowCommandChannel);
        // fake that there is a data event and invoke the handler
        if (data != null) {
            this.controlChannelRecvHandler(this._shadowCommandChannel, data);
        }
    }

    /// <summary>
    /// Count the "seconds" since the last ping.
    /// </summary>
    /// <remarks>
    /// As it turns out (at least with w2k3sp1), when the shadow
    /// session is established, virtual channels established in the
    /// in the original session of the shadower are suspended.
    /// This means the shadower will not receive the "ok" confirmation.
    /// To counter this [security?] behavior, wait for the
    /// periodic "pings" to stop, and treat the silence as confirmation.
    /// </remarks>
    this._checkLastPing = _checkLastPing;
    function _checkLastPing() {
        var skip = (this._isShadowing || this._isDisconnected);
        if (!skip) {
            this._countSinceLastPing++;
            if (this._countSinceLastPing >= 5) {
                this._raiseConnect("~5 seconds since last 'ping'");
            }
            else {
                this._setTimeout(this.Id + "._checkLastPing()", 1000);
            }
        }
    }


    /// <summary>
    /// Sends a string on the RDP virtual channel that tells rdpshadow.exe
    /// listening on this channel inside the target system to start the
    /// shadowing session.
    /// </summary>
    this.startShadowing = _startShadowing;
    function _startShadowing(){        
        // invoke _checkVirtualChannel before trying again.
        // this is doen because _checkVirtualChannel (via _pollConnection)
        // is called on a different interval than this _startShadowing.
        this._checkVirtualChannel();
        // data isn't buffered until the rdpshadow.exe tool is bound to the
        // virtual channel, so keep on sending the command for 20 seconds
        var skip = (this._isShadowing || this._isDisconnected);
        if(!skip && this._startShadowingAttempt < 10){
            log.debug("[" + this.Id + "]: RDPShadowingJavaTermClient send command to start shadowing");
            var sendOk = this._control.sendOnVirtualChannel(this._shadowCommandChannel, "shadow-v2\r\n");
            if(!sendOk){
                if (this._shadowProtoVersion < 2 && this._startShadowingAttempt > 0) {
                    // the rdpshadow.exe 5.2 (aka version 1) tool closes the
                    // channel after receiving the command to shadow.
                    // this leads to an error sending here.  once caught, raise
                    // OnConnect now because 5.2 has no explicit ok/error
                    // regarding shadow session
                    this._raiseConnect("error sending on channel after previous success, assume ok");
                    return;
                }
            }
            this._startShadowingAttempt++;
            this._setTimeout(this.Id + ".startShadowing()", 2000);
        }
        else if(!skip){
            this._raiseError("no shadow session start after 10 attempts, assume error");
        }
    }

    /// <summary>
    /// For shadowing TermClient, returns whether connected to shadow session.
    /// </summary>
    this.isConnected = _isConnected;
    function _isConnected(){
        var ret = this._controlIsConnected() && this._isShadowing;
        log.info("[" + this.Id + "]: RDPShadowingJavaTermClient.isConnected returning " + (ret? "true" : "false"));
        return ret;
    }

}
// register this instance with the TermClientFactory
termClientFactory.registerTermClient(ControlPlatform.Applet, TermClientType.RDPShadowing, "RDPShadowingJavaTermClient");


/**********************************************************************
   $Author: greynold $
   $Date: 2007/03/19 22:26:09 $
   $Revision: 1.8 $


   Copyright 2001 - 2004. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/
/// <summary>
/// Implementation class for the VmcConsole ActiveX TermClient object.
/// </summary>
/// <param name="id" type="string">the id of the TermClient instance</param>
function VmcConsoleActiveXTermClient(id){
/// region : inheritance --------------------------------------------
    this.base = TermClient;
    this.base(id);
    log.info("[" + id + "]:  VmcConsoleActiveXTermClient object created.");

/// region : private fields -----------------------------------------
    this._ctlSuffix = "_ax"; // the suffix applied to the HTML element Id
    this._frmSuffix = "_frm"; // the suffix applied to the IFrame element Id
    this._protocol = "vmx://"; // the protocol scheme for this implementation
    this._connection = null; // holds a reference to the connection object
    this._gatewayName = "/HTGateway/"; // default URL bit for the gateway server
    this._termClientType = TermClientType.VmcConsole;
    this._control = null; // holds a reference to the HTML element
    this._frame = null; // holes a reference to the IFrame element
    this._connectCount = 0; // counter for the number of permissable connection attempts
    this._successfulConnect = false; // switch for indicating when the control has successfully connected
    this._fileProxy = "ConsoleProxy.aspx"; // proxy file for downloading console connection files
    this._fileName = "VMWareConsole_"; // base .xvm file name targeted by the control
    this._fileExt = ".xvm"; // base .xvm file extension targeted by the control
    this._targetXvm = ""; // target url for the xvm file
    this._verifyCount = 0; // counter for the number of connection verification attempts    
    this._hostURL = ""; // holds the complete URL for the host
    this._gatewayURL = ""; // holds the complete URL for the gateway
    this._hasDownloaded = false; // boolean flag set to true once the .xvm has been downloaded

/// region : Properties ---------------------------------------------

    /// <summary>
    /// Gets/sets the Protocol for this object.
    /// </summary>
    this.Protocol = TermClientProtocol.VmcConsole;

    /// <summary>
    /// Gets/sets the ControlPlatform for this object.
    /// </summary>
    this.Platform = ControlPlatform.ActiveX;

    /// <summary>
    /// Gets/sets the TermClientType for this object.
    /// </summary>
    this.TermClientType = TermClientType.VmcConsole;

    /// <summary>
    /// Gets/sets the host IP address for this object.
    /// </summary>
    this.HostAddress = "";

    /// <summary>
    /// Gets/sets the destination port for this object.
    /// </summary>
    this.HostPort = "";

    /// <summary>
    /// Gets/sets the vm name for this object.
    /// </summary>
    this.VmName = "";

    /// <summary>
    /// Gets/sets the width setting for this object.
    /// </summary>
    this.Width = 0;

    /// <summary>
    /// Gets/sets the height setting for this object.
    /// </summary>
    this.Height = 0;

    /// <summary>
    /// Gets/sets the HTML element reference this TermClient instance is loaded in.
    /// </summary>
    this.Element = null;

    /// <summary>
    /// Gets/sets the Username to use when connecting to this TermClient host.
    /// </summary>
    this.Username = "";

    /// <summary>
    /// Gets/sets the Password to use when connecting to this TermClient host.
    /// </summary>
    this.Password = "";

    /// <summary>
    /// Gets/sets the Username required to authenticate via the TermClient's protocol.
    /// </summary>
    this.ProtocolUsername = "";

    /// <summary>
    /// Gets/sets the Password required to authenticate via the TermClient's protocol.
    /// </summary>
    this.ProtocolPassword = "";

    /// <summary>
    /// Gets/sets the Password required to authenticate on the vm's Host.
    /// </summary>
    this.HostUsername = "";

    /// <summary>
    /// Gets/sets the Password required to authenticate on the vm's Host.
    /// </summary>
    this.HostPassword = "";

/// region : Methods ------------------------------------------------

    /// <summary>
    /// Method handles any initialization needed for the control before the connect() method 
    /// is called.  Not all controls will implement the init() method therefore this is not 
    /// a "virtual" method, just an empty stub that must be overridden for any effect to occur.
    /// </summary>
    /// <param name="args" type="object">initialization arguments, this is dependent upon implementation</param>
    this.init = _init;
    function _init(args){
        // no noop call here, if a control does not override, fail silently.
        return;
    }

        /// <summary>
    /// Method renders the TermClient's HTML to the target frame's document.  The method 
    /// of render varies for each implementation.
    /// </summary>
    this.renderHtml = _renderHtml;
    function _renderHtml() {
        var ctlid = this.Id + this._ctlSuffix;
        return '<object id="' + ctlid + '" ' +
            'classid="CLSID:380BBEC2-4CAE-4ECE-8AFF-36CDE7916386" ' +
            'codebase="' + appPath + '/URA/lib/LocalProxyActiveX.cab#Version=5,0,0,0"></object>' + 
            '<br/><br/><br/><br/><center><div style="width:60%;font-family:Verdana,Trebuchet,Arial,Helvetica;font-size:12px;">' + 
            'The requested Virtual Machine connection will open in another application.  ' + 
            'You must accept the pop-up window, download the file and open it in order to complete the connection.  ' + 
            'Once you have connected, <em>do not</em> close this window or your connection will be terminated.' + 
            '</div></center>';
    }

    /// <summary>
    /// Method tells the TunnelConfig to attempt to start the remote session. Raises 
    /// an OnConnect event.
    /// </summary>
    this.connect = _connect;
    function _connect(){
        try{
            // get the ref to the HTML element
            if(this._control == null){
                this._control = this.Element.getElementById(this.Id + this._ctlSuffix);
                if(this._control == null){
                    log.error("[" + this.Id + "]:  VmcConsoleActiveXTermClient unable to find rendered object tag in document.");
                    throw this._newError("Unable to target control HTML tag");
                }
            }
            log.debug("[" + this.Id + "]:  VmcConsoleActiveXTermClient._control = " + this._control);
            
            if(typeof(this._control.NewConnection) != "undefined"){
                log.info("[" + this.Id + "]:  VmcConsoleActiveXTermClient attempting to connect to host: " + this.HostAddress + ":" + this.HostPort);
                this._connectCount = 0;

                // create the connection object using the destination address
                if(this.HostAddress != ""){
                    if(this.HostPort != ""){
                        this._hostURL = this.Protocol + "://" + this.HostAddress + ":" + this.HostPort;
                    } else {
                        this._hostURL = this.Protocol + "://" + this.HostAddress;
                    }
                    log.info("[" + this.Id + "]:  VmcConsoleActiveXTermClient establishing connection to host: " + this._hostURL);
                    this._connection = this._control.NewConnection(this._hostURL);
                } else {
                    log.error("[" + this.Id + "]:  VmcConsoleActiveXTermClient.HostAddress property is invalid and cannot be connected.");
                    throw this._newError("HostAddress property is invalid.");
                }

                // set the connection classname
                this._connection.GetPropertyBag().SetProperty("ProxyConnection.connectionClasses", "SocketConnection");

                // set the logging for the control
                this._control.EnableFileLogging("c:\\temp\\Surgient_VmcConsoleActiveXTermClient.log");

                // now try to start the connection
                this._connection.Start();
                
                // finally set up a callback to verify the connection was made
                this._setTimeout(this.Id + "._verifyConnection()", 1000);

            } else {
                // if the control has tried to connect 5 times, it's not going to be 
                // successful so message that up to a handler
                if(this._connectCount < 25){
                    // the ActiveX control is not yet ready, so re-call this function after 
                    // a set timeout
                    this._setTimeout(this.Id + ".connect()", 1000);
                    this._connectCount++;
                } else {
                    log.fatal("[" + this.Id + "]:  VmcConsoleActiveXTermClient control unable to initialize due to a download or installation error.");
                    // raise an OnLoadError event
                    this._raiseEvent("OnLoadError", null);
                }
            }
        } catch(e){
            log.fatal("[" + this.Id + "]:  VmcConsoleActiveXTermClient suffered a fatal error during the connect() method: " + e.message);
            this.connectError(e);
            return;
        }
    }

    /// <summary>
    /// Private method to verify the TunnelConfig's connection before raising the OnConnect event.
    /// </summary>    
    this._verifyConnection = _verifyConnection;
    function _verifyConnection(){
        try
        {
            if(this._connection == null){
                log.error("[" + this.Id + "]:  VmcConsoleActiveXTermClient control's Connection object was uninstantiated.");
                throw this._newError("Connection was uninstantiated in ActiveX control.");
            }
            if(this.isConnected()){
                log.info("[" + this.Id + "]:  VmcConsoleActiveXTermClient successfully connected to host: " + this._hostURL);
                if(!this._hasDownloaded){
                    this._targetXvm = appPath + "/" + this._fileName + this.Id + this._fileExt + 
                        "?hostIp=" + this.getDestinationIPAddress() + 
                        "&hostPort=" + this.getDestinationPort() + 
                        "&userName=" + this.HostUsername + 
                        "&password=" + this.HostPassword + 
                        "&hostType=" + this.HostType + 
                        '&vmfile="' + this.VmFile + '"';
                    var encodedXvm = this._urlEncode(this._targetXvm);
                    var proxyPath = appPath + "/" + this._fileProxy + "?path=" + encodedXvm;

                    var win = window.open(proxyPath, "SurgientDownloads", "width=480,height=200");
                    this._hasDownloaded = true;
                }
                // begin the client connection polling cycle to see if it responds
                this._setTimeout(this.Id + "._verifyClientConnection()", 1000);
            } else {
                if(this._verifyCount < 20){
                    this._verifyCount++;
                    this._setTimeout(this.Id + "._verifyConnection()", 1000);
                } else {
                    log.error("[" + this.Id + "]:  VmcConsoleActiveXTermClient was unable to verify to host: " + this._hostURL);
                    throw this._newError("VmcConsoleActiveXTermClient connection verification failed.");
                }
            }
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  VmcConsoleActiveXTermClient suffered a fatal error attempting to verify the connection: " + e.message);
            this.connectError(e);
            return;
        }
    }    

    /// <summary>
    /// Private method to verify that the external client has connected through this TermClient
    /// </summary>  
    this._verifyClientConnection = _verifyClientConnection;
    function _verifyClientConnection(){
        try
        {
            if(this._connection == null){
                log.error("[" + this.Id + "]:  VmcConsoleActiveXTermClient control's Connection object was uninstantiated.");
                throw this._newError("Connection was uninstantiated in ActiveX control.");
            }
            if(this.isConnected() && this._connection.GetConnectionCount() > 0){
                // prevent any more connections to this object
                //this._connection.Stop();
                // begin cyclical polling of the connection to make sure things are working
                this._setTimeout(this.Id + "._pollConnection()", 1500);
                this._raiseEvent("OnConnect", null);
            } else {
                if(this._verifyCount < 20){
                    this._verifyCount++;
                    this._setTimeout(this.Id + "._verifyClientConnection()", 1000);
                } else {
                    throw this._newError("VmcConsoleActiveXTermClient client connection verification failed.");
                }
            }
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  VmcConsoleActiveXTermClient suffered a fatal error attempting to verify the client connection: " + e.message);
            this.connectError(e);
            return;
        }
    }
    
    /// <summary>
    /// Private method that polls the control every second to determine if the 
    /// connection is still viable.  If not, it raises the OnDisconnect event.
    /// </summary>
    this._pollConnection = _pollConnection;
    function _pollConnection(){
        //if(this.isConnected() && !this._connection.IsStoppedOk()){
          if(this.isConnected() && this._connection.GetConnectionCount() > 0){
            this._setTimeout(this.Id + "._pollConnection()", 1000);
        } else {
            log.info("[" + this.Id + "]:  VmcConsoleActiveXTermClient connection poll returned a disconnected state.");
            this._connection.Stop();
            this._setTimeout(this.Id + '._raiseEvent("OnDisconnect", null)', 2000);
        }
    }

    /// <summary>
    /// Method tells the TunnelConfig to attempt to disconnect.
    /// </summary>
    this.disconnect = _disconnect;
    function _disconnect(args) {
        // calls the Abort() method on the connection object
        this._connection.Stop();
        log.info("[" + this.Id + "]:  VmcConsoleActiveXTermClient successfully disconnected from host: " + this._hostURL + " via gateway: " + this._gatewayURL);
        // raise the OnDisconnect event, passing the results up the chain
        this._raiseEvent("OnDisconnect", args);
    }

    /// <summary>
    /// Method called by the TunnelConfig instance when a connection error has occurred.  Raises 
    /// an OnConnectError event.
    /// </summary>
    this.connectError = _connectError;
    function _connectError(error) {
        log.error("[" + this.Id + "]:  VmcConsoleActiveXTermClient failed to connect to host: " + this._hostURL + " via gateway: " + this._gatewayURL);
        // raise the OnConnectError event
        this._raiseEvent("OnConnectError", error.message);
    }

    /// <summary>
    /// Method determines if the control is actually connected or not, helpful for polling 
    /// exercises and error checking in the URACoordinators.
    /// </summary>
    this.isConnected = _isConnected;
    function _isConnected(){
        try
        {
            if(this._connection.IsStartedOk()){
                log.info("[" + this.Id + "]:  VmcConsoleActiveXTermClient.isConnected returned: true");
                return true;
            } else {
                log.info("[" + this.Id + "]:  VmcConsoleActiveXTermClient.isConnected returned: false");
                return false;
            }
        }
        catch (e)
        {
            log.info("[" + this.Id + "]:  VmcConsoleActiveXTermClient.isConnected caught the following exception: " + e.message);
            throw this._newError("VmcConsoleActiveXTermClient.isConnected raised exception.");
        }
    }

    /// <summary>
    /// Method gets the ActiveX or Applet control of the TermClient depending upon what 
    /// ControlPlatform has been deployed.
    /// </summary>
    /// <return type="object">the internal control, if this control has not been properly
    /// initialized this method ***can return null***</return>
    this.getControl = _getControl;
    function _getControl(){
        return this._control;
    }

    /// <summary>
    /// Gets the local IPAddress of the TunnelConfig.
    /// </summary>
    /// <return type="string">the local IPAddress of the TunnelConfig</return>
    this.getDestinationIPAddress = _getDestinationIPAddress;
    function _getDestinationIPAddress() {
        try
        {
        	return this._connection.GetLocalIPString();
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  VmcConsoleActiveXTermClient.getDestinationIPAddress() suffered a fatal error: " + e.message);
            throw this._newError("VmcConsoleActiveXTermClient connection does not return address: " + e.message);
        }
    }

    /// <summary>
    /// Gets the local Port of the TunnelConfig.
    /// </summary>
    this.getDestinationPort = _getDestinationPort;
    function _getDestinationPort() {
        try
        {
        	return this._connection.GetLocalPort();
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  VmcConsoleActiveXTermClient.getDestinationPort() suffered a fatal error: " + e.message);
            throw this._newError("VmcConsoleActiveXTermClient connection does not return port: " + e.message);
        }
    }

    /// <summary>
    /// Method to send Ctrl+Alt+Delete to the TermClient control
    /// </summary>
    this.sendCtrlAltDelete = _sendCtrlAltDelete;
    function _sendCtrlAltDelete(){
        alert("You must use the VMware client to send keys to the virtual machine.");
    }

    /// <summary>
    /// Method to retrieve the key commands to send Ctrl+Alt+Delete to the TermClient control.
    /// </summary>
    this.getCADCommand = _getCADCommand;
    function _getCADCommand(){
        // send null because the key command is supported by the control
        return null;
    }

    /// <summary>
    /// Method encodes a plaintext string into a URL safe format
    /// </summary>
    /// <param type="string" name="plaintext">the text to encode</param>
    /// <return type="string">the urlencoded string</return>
    this._urlEncode = _urlEncode;
    function _urlEncode(plaintext)
    {
        var safechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_.!~*'()";
        var HEX = "0123456789ABCDEF";
        var encoded = "";
        for (var i = 0; i < plaintext.length; i++ ) {
            var ch = plaintext.charAt(i);
            if (ch == " ") {
                encoded += "+";
            } else if (safechars.indexOf(ch) != -1) {
                encoded += ch;
            } else {
                var charCode = ch.charCodeAt(0);
                if (charCode > 255) {
                    encoded += "+";
                } else {
                    encoded += "%";
                    encoded += HEX.charAt((charCode >> 4) & 0xF);
                    encoded += HEX.charAt(charCode & 0xF);
                }
            }
        }
        return encoded;
    }
}
// register this instance with the TermClientFactory
termClientFactory.registerTermClient(ControlPlatform.ActiveX, TermClientType.VmcConsole, "VmcConsoleActiveXTermClient");


/**********************************************************************
   $Author: greynold $
   $Date: 2007/07/10 18:37:37 $
   $Revision: 1.9 $


   Copyright 2001 - 2004. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/
/// <summary>
/// Implementation class for the VmcConsole Applet TermClient object.
/// </summary>
/// <param name="id" type="string">the id of the TermClient instance</param>
function VmcConsoleJavaTermClient(id){
/// region : inheritance --------------------------------------------
    this.base = TermClient;
    this.base(id);
    log.info("[" + id + "]:  VmcConsoleJavaTermClient object created.");

/// region : private fields -----------------------------------------
    this._ctlSuffix = "_ax"; // the suffix applied to the HTML element Id
    this._frmSuffix = "_frm"; // the suffix applied to the IFrame element Id
    this._protocol = "vmx://"; // the protocol scheme for this implementation
    this._connection = null; // holds a reference to the connection object
    this._gatewayName = "/HTGateway/"; // default URL bit for the gateway server
    this._termClientType = TermClientType.VmcConsole;
    this._control = null; // holds a reference to the HTML element
    this._frame = null; // holes a reference to the IFrame element
    this._connectCount = 0; // counter for the number of permissable connection attempts
    this._successfulConnect = false; // switch for indicating when the control has successfully connected
    this._fileProxy = "ConsoleProxy.aspx"; // proxy file for downloading console connection files
    this._fileName = "VMWareConsole_"; // base .xvm file name targeted by the control
    this._fileExt = ".xvm"; // base .xvm file extension targeted by the control
    this._targetXvm = ""; // target url for the xvm file
    this._verifyCount = 0; // counter for the number of connection verification attempts    
    this._hostURL = ""; // holds the complete URL for the host
    this._gatewayURL = ""; // holds the complete URL for the gateway
    this._hasDownloaded = false; // boolean flag set to true once the .xvm has been downloaded

/// region : Properties ---------------------------------------------

    /// <summary>
    /// Gets/sets the name of the class that handles the upstream encoding.  This must be one of the following
    /// values:  "" or a comma delimited list of:  "OctetStreamUpHandler", "MultipartFormUpHandler" , "Base64UpHandler"
    /// </summary>   
    this.UpstreamHandler = "com.surgient.localproxy.connections.http.OctetStreamHandler$UpHandler,com.surgient.localproxy.connections.http.MultipartFormUpHandler,com.surgient.localproxy.connections.http.Base64Handler$UpHandler";
    
    /// <summary>
    /// Gets/sets the name of the class that handles the downstream encoding.  This must be one of the following
    /// values:  "" or a comma delimited list of:  "OctetStreamDnHandler", "Base64DnHandler"
    /// </summary>  
    this.DownstreamHandler = "com.surgient.localproxy.connections.http.OctetStreamHandler$DnHandler,com.surgient.localproxy.connections.http.Base64Handler$DnHandler";

    /// <summary>
    /// Gets/sets the Protocol for this object.
    /// </summary>
    this.Protocol = TermClientProtocol.VmcConsole;

    /// <summary>
    /// Gets/sets the ControlPlatform for this object.
    /// </summary>
    this.Platform = ControlPlatform.Applet;

    /// <summary>
    /// Gets/sets the TermClientType for this object.
    /// </summary>
    this.TermClientType = TermClientType.VmcConsole;

    /// <summary>
    /// Gets/sets the host IP address for this object.
    /// </summary>
    this.HostAddress = "";

    /// <summary>
    /// Gets/sets the destination port for this object.
    /// </summary>
    this.HostPort = "";

    /// <summary>
    /// Gets/sets the vm name for this object.
    /// </summary>
    this.VmName = "";

    /// <summary>
    /// Gets/sets the width setting for this object.
    /// </summary>
    this.Width = 0;

    /// <summary>
    /// Gets/sets the height setting for this object.
    /// </summary>
    this.Height = 0;

    /// <summary>
    /// Gets/sets the HTML element reference this TermClient instance is loaded in.
    /// </summary>
    this.Element = null;

    /// <summary>
    /// Gets/sets the Username to use when connecting to this TermClient host.
    /// </summary>
    this.Username = "";

    /// <summary>
    /// Gets/sets the Password to use when connecting to this TermClient host.
    /// </summary>
    this.Password = "";

    /// <summary>
    /// Gets/sets the Username required to authenticate via the TermClient's protocol.
    /// </summary>
    this.ProtocolUsername = "";

    /// <summary>
    /// Gets/sets the Password required to authenticate via the TermClient's protocol.
    /// </summary>
    this.ProtocolPassword = "";

    /// <summary>
    /// Gets/sets the Password required to authenticate on the vm's Host.
    /// </summary>
    this.HostUsername = "";

    /// <summary>
    /// Gets/sets the Password required to authenticate on the vm's Host.
    /// </summary>
    this.HostPassword = "";

/// region : Methods ------------------------------------------------

    /// <summary>
    /// Method handles any initialization needed for the control before the connect() method 
    /// is called.  Not all controls will implement the init() method therefore this is not 
    /// a "virtual" method, just an empty stub that must be overridden for any effect to occur.
    /// </summary>
    /// <param name="args" type="object">initialization arguments, this is dependent upon implementation</param>
    this.init = _init;
    function _init(args){
        // no noop call here, if a control does not override, fail silently.
        return;
    }

        /// <summary>
    /// Method renders the TermClient's HTML to the target frame's document.  The method 
    /// of render varies for each implementation.
    /// </summary>
    this.renderHtml = _renderHtml;
    function _renderHtml() {
        var ctlid = this.Id + this._ctlSuffix;
        return '<applet id="' + ctlid + '" code="com.surgient.localproxy.applet.ProxyApplet.class" archive="' + appPath + '/URA/lib/LocalProxyApplet.jar"' + 
            ' height="0" width="0">' + 
            '<param name="logLevel" value="5" />' + 
            '<param name="cabbase" value="' + appPath + '/URA/lib/LocalProxyApplet11.cab" />' + 
            '</applet>' + 
            '<br/><br/><br/><br/><center><div style="width:60%;font-family:Verdana,Trebuchet,Arial,Helvetica;font-size:12px;">' + 
            'The requested Virtual Machine connection will open in another application.  ' + 
            'You must accept the pop-up window, download the file and open it in order to complete the connection.  ' + 
            'Once you have connected, <em>do not</em> close this window or your connection will be terminated.' + 
            '</div></center>';
    }

    /// <summary>
    /// Method tells the TunnelConfig to attempt to start the remote session. Raises 
    /// an OnConnect event.
    /// </summary>
    this.connect = _connect;
    function _connect(){
        try{
            // get the ref to the HTML element
            if(this._control == null){
                this._control = this.Element.getElementById(this.Id + this._ctlSuffix);
                if(this._control == null){
                    log.error("[" + this.Id + "]:  VmcConsoleJavaTermClient unable to find rendered object tag in document.");
                    throw this._newError("Unable to target control HTML tag");
                }
            }
            log.debug("[" + this.Id + "]:  VmcConsoleJavaTermClient._control = " + this._control.tagName);
            
            try
            {
            	// the isStarted method is a simple boolean test, the results of which don't matter 
                // at this point, to verify that the control has been loaded properly this method just 
                // needs to return a value and not throw an exception because the method is not supported.
                if(this._control.isStarted()){
                    log.info("[" + this.Id + "]:  VmcConsoleJavaTermClient attempting to connect to host: " + this.HostAddress + ":" + this.HostPort);
                    this._connectCount = 0;

                    // create the connection object using the destination address
                    if(this.HostAddress != ""){
                        if(this.HostPort != ""){
                            this._hostURL = this.Protocol + "://" + this.HostAddress + ":" + this.HostPort;
                        } else {
                            this._hostURL = this.Protocol + "://" + this.HostAddress;
                        }
                        log.info("[" + this.Id + "]:  VmcConsoleJavaTermClient establishing connection to host: " + this._hostURL);
                        this._connection = this._control.newConnection(this._hostURL);
                    } else {
                        log.error("[" + this.Id + "]:  VmcConsoleJavaTermClient.HostAddress property is invalid and cannot be connected.");
                        throw this._newError("HostAddress property is invalid.");
                    }

                    // set the connection classname
                    this._connection.getPropertyBag().setProperty("ProxyConnection.connectionClasses", "com.surgient.localproxy.connections.socket.SocketConnection");

                    // now try to start the connection
                    this._connection.asyncStart();

                    // finally set up a callback to verify the connection was made
                    this._setTimeout(this.Id + "._verifyConnection()", 1000);                    
                } else {
                    log.error("[" + this.Id + "]: LocalProxy applet does not show isStarted method.");
                    throw this._newError("No isStarted method");
                }
            }
            catch (ex)
            {
                log.debug("[" + this.Id + "]:  VmcConsoleJavaTermClient control error while trying to start: " + ex.message);
                // if the control has tried to connect 25 times, it's not going to be 
                // successful so message that up to a handler
                if(this._connectCount < 25){
                    // the ActiveX control is not yet ready, so re-call this function after a set timeout
                    this._setTimeout(this.Id + ".connect()", 1000);
                    this._connectCount++;
                } else {
                    log.fatal("[" + this.Id + "]:  VmcConsoleJavaTermClient control unable to initialize due to a download or installation error.");
                    // raise an OnLoadError event
                    this._raiseEvent("OnLoadError", null);
                }
            }
        } catch(e){
            log.fatal("[" + this.Id + "]:  VmcConsoleJavaTermClient suffered a fatal error during the connect() method: " + e.message);
            this.connectError(e);
            return;
        }
    }

    /// <summary>
    /// Private method to verify the TunnelConfig's connection before raising the OnConnect event.
    /// </summary>    
    this._verifyConnection = _verifyConnection;
    function _verifyConnection(){
        try
        {
            if(this._connection == null){
                log.error("[" + this.Id + "]:  VmcConsoleJavaTermClient control's Connection object was uninstantiated.");
                throw this._newError("Connection was uninstantiated in ActiveX control.");
            }
            if(this.isConnected()){
                log.info("[" + this.Id + "]:  VmcConsoleJavaTermClient successfully connected to host: " + this._hostURL);
                if(!this._hasDownloaded){
                    this._targetXvm = appPath + "/" + this._fileName + this.Id + this._fileExt + 
                        "?hostIp=" + this.getDestinationIPAddress() + 
                        "&hostPort=" + this.getDestinationPort() + 
                        "&userName=" + this.HostUsername + 
                        "&password=" + this.HostPassword + 
                        '&vmfile="' + this.VmFile + '"';
                    var encodedXvm = this._urlEncode(this._targetXvm);
                    var proxyPath = appPath + "/" + this._fileProxy + "?path=" + encodedXvm;

                    var win = window.open(proxyPath, "SurgientDownloads", "width=480,height=200");
                    this._hasDownloaded = true;
                }
                // begin the client connection polling cycle to see if it responds
                this._setTimeout(this.Id + "._verifyClientConnection()", 1000);
            } else {
                if(this._verifyCount < 20){
                    this._verifyCount++;
                    this._setTimeout(this.Id + "._verifyConnection()", 1000);
                } else {
                    log.error("[" + this.Id + "]:  VmcConsoleJavaTermClient was unable to verify to host: " + this._hostURL);
                    throw this._newError("VmcConsoleJavaTermClient connection verification failed.");
                }
            }
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  VmcConsoleJavaTermClient suffered a fatal error attempting to verify the connection: " + e.message);
            this.connectError(e);
            return;
        }
    }    

    /// <summary>
    /// Private method to verify that the external client has connected through this TermClient
    /// </summary>  
    this._verifyClientConnection = _verifyClientConnection;
    function _verifyClientConnection(){
        try
        {
            if(this._connection == null){
                log.error("[" + this.Id + "]:  VmcConsoleJavaTermClient control's Connection object was uninstantiated.");
                throw this._newError("Connection was uninstantiated in ActiveX control.");
            }
            if(this.isConnected() && this._connection.getConnectionCount() > 0){
                // prevent any more connections to this object
                //this._connection.Stop();
                // begin cyclical polling of the connection to make sure things are working
                this._setTimeout(this.Id + "._pollConnection()", 1500);
                this._raiseEvent("OnConnect", null);
            } else {
                if(this._verifyCount < 20){
                    this._verifyCount++;
                    this._setTimeout(this.Id + "._verifyClientConnection()", 1000);
                } else {
                    throw this._newError("VmcConsoleJavaTermClient client connection verification failed.");
                }
            }
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  VmcConsoleJavaTermClient suffered a fatal error attempting to verify the client connection: " + e.message);
            this.connectError(e);
            return;
        }
    }
    
    /// <summary>
    /// Private method that polls the control every second to determine if the 
    /// connection is still viable.  If not, it raises the OnDisconnect event.
    /// </summary>
    this._pollConnection = _pollConnection;
    function _pollConnection(){
        if(this.isConnected() && this._connection.getConnectionCount() > 0){
            this._setTimeout(this.Id + "._pollConnection()", 1000);
        } else {
            log.info("[" + this.Id + "]:  VmcConsoleJavaTermClient connection poll returned a disconnected state.");
            this._connection.asyncStop();
            this._setTimeout(this.Id + '._raiseEvent("OnDisconnect", null)', 2000);
        }
    }

    /// <summary>
    /// Method tells the TunnelConfig to attempt to disconnect.
    /// </summary>
    this.disconnect = _disconnect;
    function _disconnect(args) {
        // calls the Abort() method on the connection object
        this._connection.asyncStop();
        log.info("[" + this.Id + "]:  VmcConsoleJavaTermClient successfully disconnected from host: " + this._hostURL + " via gateway: " + this._gatewayURL);
        // raise the OnDisconnect event, passing the results up the chain
        this._raiseEvent("OnDisconnect", args);
    }

    /// <summary>
    /// Method called by the TunnelConfig instance when a connection error has occurred.  Raises 
    /// an OnConnectError event.
    /// </summary>
    this.connectError = _connectError;
    function _connectError(error) {
        log.error("[" + this.Id + "]:  VmcConsoleJavaTermClient failed to connect to host: " + this._hostURL + " via gateway: " + this._gatewayURL);
        // raise the OnConnectError event
        this._raiseEvent("OnConnectError", error.message);
    }

    /// <summary>
    /// Checks the applet for whether it is connected.
    /// True/False indicates connection state; throws on connection error.
    /// </summary>
    this._checkConnected = _checkConnected;
    function _checkConnected(){
        try {
            var ret = this._connection.isStartedOk();
            if (ret >= 0) {
                return (ret > 0)? true : false;
            }
        }
        catch (e) {
            log.warn("[" + this.Id + "]:  VmcConsoleJavaTermClient._checkConnected cannot verify applet isStartedOk()");
            return false;
        }
        // isStartedOk() returned error (<0)
        var errorMessage;
        try {
            errorMessage = this._connection.getLastError().getMessage();
        }
        catch (e) {
            errorMessage = "applet isStartedOk() returned error";
        }
        log.warn("[" + this.Id + "]:  VmcConsoleJavaTermClient._checkConnected: applet error: " + errorMessage);
        throw this._newError(errorMessage);
    }

    /// <summary>
    /// Method determines if the control is actually connected or not, helpful for polling
    /// exercises and error checking in the URACoordinators.
    /// </summary>
    this.isConnected = _isConnected;
    function _isConnected(){
        try
        {
            if (this._checkConnected()) {
                log.info("[" + this.Id + "]:  VmcConsoleJavaTermClient.isConnected returned: true");
                return true;
            }
            else {
                log.info("[" + this.Id + "]:  VmcConsoleJavaTermClient.isConnected returned: false");
                return false;
            }
        }
        catch (e)
        {
            log.info("[" + this.Id + "]:  VmcConsoleJavaTermClient.isConnected returned: false");
            return false;
        }
    }

    /// <summary>
    /// Method gets the ActiveX or Applet control of the TermClient depending upon what 
    /// ControlPlatform has been deployed.
    /// </summary>
    /// <return type="object">the internal control, if this control has not been properly
    /// initialized this method ***can return null***</return>
    this.getControl = _getControl;
    function _getControl(){
        return this._control;
    }

    /// <summary>
    /// Gets the local IPAddress of the TunnelConfig.
    /// </summary>
    /// <return type="string">the local IPAddress of the TunnelConfig</return>
    this.getDestinationIPAddress = _getDestinationIPAddress;
    function _getDestinationIPAddress() {
        try
        {
            var addr = this._connection.getLocalAddress();
            if (addr == null) {
                var ex = this._connection.getLastError();
                if (ex != null) {
                    throw this._newError("applet getLocalAddress() error: " + ex.getMessage());
                }
                else {
                    throw this._newError("applet getLocalAddress() returned null");
                }
            }
            return addr.getHostAddress();
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  VmcConsoleJavaTermClient.getDestinationIPAddress() suffered a fatal error: " + e.message);
            throw this._newError("VmcConsoleJavaTermClient connection does not return address: " + e.message);
        }
    }

    /// <summary>
    /// Gets the local Port of the TunnelConfig.
    /// </summary>
    this.getDestinationPort = _getDestinationPort;
    function _getDestinationPort() {
        try
        {
            var port = this._connection.getLocalPort();
            if (port == 0) {
                var ex = this._connection.getLastError();
                if (ex != null) {
                    throw this._newError("applet getLocalPort() error: " + ex.getMessage());
                }
                else {
                    throw this._newError("applet getLocalPort() returned 0");
                }
            }
            return port;
        }
        catch (e)
        {
            log.error("[" + this.Id + "]:  VmcConsoleJavaTermClient.getDestinationPort() suffered a fatal error: " + e.message);
            throw this._newError("VmcConsoleJavaTermClient connection does not return port: " + e.message);
        }
    }

    /// <summary>
    /// Method to send Ctrl+Alt+Delete to the TermClient control
    /// </summary>
    this.sendCtrlAltDelete = _sendCtrlAltDelete;
    function _sendCtrlAltDelete(){
        alert("You must use the VMware client to send keys to the virtual machine.");
    }

    /// <summary>
    /// Method to retrieve the key commands to send Ctrl+Alt+Delete to the TermClient control.
    /// </summary>
    this.getCADCommand = _getCADCommand;
    function _getCADCommand(){
        // send null because the key command is supported by the control
        return null;
    }

    /// <summary>
    /// Method encodes a plaintext string into a URL safe format
    /// </summary>
    /// <param type="string" name="plaintext">the text to encode</param>
    /// <return type="string">the urlencoded string</return>
    this._urlEncode = _urlEncode;
    function _urlEncode(plaintext)
    {
        var safechars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz-_.!~*'()";
        var HEX = "0123456789ABCDEF";
        var encoded = "";
        for (var i = 0; i < plaintext.length; i++ ) {
            var ch = plaintext.charAt(i);
            if (ch == " ") {
                encoded += "+";
            } else if (safechars.indexOf(ch) != -1) {
                encoded += ch;
            } else {
                var charCode = ch.charCodeAt(0);
                if (charCode > 255) {
                    encoded += "+";
                } else {
                    encoded += "%";
                    encoded += HEX.charAt((charCode >> 4) & 0xF);
                    encoded += HEX.charAt(charCode & 0xF);
                }
            }
        }
        return encoded;
    }
}
// register this instance with the TermClientFactory
termClientFactory.registerTermClient(ControlPlatform.Applet, TermClientType.VmcConsole, "VmcConsoleJavaTermClient");


/**********************************************************************
   $Author: csanford $
   $Date: 2009/03/02 21:54:47 $
   $Revision: 1.19.10.2 $


   Copyright 2001 - 2004. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/

/// <summary>
/// Implementation class for the Citrix ActiveX TermClient object.
/// </summary>
/// <param name="id" type="string">the id of the TermClient instance</param>
function VNCActiveXTermClient(id){
/// region : inheritance --------------------------------------------
    this.base = TermClient;
    this.base(id);
    log.info("[" + id + "]:  VNCActiveXTermClient object created.");

/// region : private fields -----------------------------------------
    this._ctlSuffix = "_ax";

/// region : private fields -----------------------------------------
    this._termClientType = TermClientType.Citrix;
    this._control = null; // holds a reference to the HTML element
    this._connectCount = 25; // counter for the number of permissable connection attempts
    this._connectStarted = false; // switch until the connection has attempted to be started
    this._connectComplete = false; // switch until the connection has been verifiably completed
    this._timeout = null; // pointer to a cancellable window.Timeout object

/// region : Properties ---------------------------------------------

    /// <summary>
    /// Gets/sets the Protocol for this object.
    /// </summary>
    this.Protocol = TermClientProtocol.VNC;

    /// <summary>
    /// Gets/sets the ControlPlatform for this object.
    /// </summary>
    this.Platform = ControlPlatform.ActiveX;

    /// <summary>
    /// Gets/sets the TermClientType for this object.
    /// </summary>
    this.TermClientType = TermClientType.VNC;

    /// <summary>
    /// Gets/sets the control's ScalingMode property.  See control ScalingMode docs.
    /// </summary>
    this.ScalingMode = 0;

    /// <summary>
    /// Gets/sets the control's Desired color depth property.  See control DesiredColor docs.
    /// </summary>
    this.DesiredColor = 16;


/// region : Methods ------------------------------------------------

    /// <summary>
    /// Method handles any initialization needed for the control before the connect() method 
    /// is called.  Not all controls will implement the init() method therefore this is not 
    /// a "virtual" method, just an empty stub that must be overridden for any effect to occur.
    /// </summary>
    /// <param name="args" type="object">initialization arguments, this is dependent upon implementation</param>
    this.init = _init;
    function _init(args){
        // no noop call here, if a control does not override, fail silently.
        return;
    }

    /// <summary>
    /// Method tells the TermClient to attempt to start the remote session. Raises 
    /// an OnConnect event.
    /// </summary>
    this.connect = _connect;
    function _connect(){        
        // create a counter for the number of connection attempts
        if(typeof(this._connectionAttempt) == "undefined"){
            this._connectionAttempt = 0;
        }
        try
        {
            // find our control and bind to it
            this._control = this.Element.getElementById(this.Id + this._ctlSuffix);
            if(this._control == null){
                log.error("[" + this.Id + "]:  VNCActiveXTermClient unable to find rendered object tag in document.");
                throw this._newError("No download error.");
            }
            log.debug("[" + this.Id + "]:  VNCActiveXTermClient._control = " + this._control);
            this._hostURL = this.Protocol + "://" + this.HostAddress + ":" + this.HostPort;

            if(this._control == null || typeof(this._control.GetConnectionState) == "undefined"){
                log.info("[" + this.Id + "]:  VNCActiveXTermClient attempting connection:  " + this._connectionAttempt);
                if(this._connectionAttempt < this._connectCount){
                    this._connectionAttempt++;
                    this._setTimeout(this.Id + ".connect()", 1000);
                } else {
                    this._raiseEvent("OnLoadError", null);
                }
            } else {
                log.info("[" + this.Id + "]:  VNCActiveXTermClient preparing to connect.");
                this._control.ConnectAsync();
                this._connectStarted = true;
                this._hostURL = this.Protocol + "://" + this.HostAddress + ":" + this.HostPort;
                this._setTimeout(this.Id + "._verifyConnection()", 1000);
            }
        }
        catch (e)
        {
            if(e.message == "No download error."){
                log.fatal("[" + this.Id + "]:  VNCActiveXTermClient control unable to initialize due to download or installation error.");
            } else {
                log.fatal("[" + this.Id + "]:  VNCActiveXTermClient control suffered a fatal initialization error: " + e.message);
            }
            this._raiseEvent("OnConnectError", null);
        }
    }

    /// <summary>
    /// A polling method that will attempt to determine if the control has successfully 
    /// connected or not when the control does not support callback mechanisms for the connection event.
    /// </summary>
    this._verifyConnection = _verifyConnection;
    function _verifyConnection(){
        if(typeof(this._verifyConnectionAttempt) == "undefined"){
            this._verifyConnectionAttempt = 0;
        }
        if(this.isConnected()){
            // the control is connected so begin the connection polling process
            this._setTimeout(this.Id + "._pollConnection()", 1000);
            // fake that there was a control connection event by calling the handler
            this.controlConnectHandler();
        } else {
            if(this._verifyConnectionAttempt < this._connectCount){
                this._verifyConnectionAttempt++;
                log.info("[" + this.Id + "]:  VNCActiveXTermClient attempting connection verification:  " + this._verifyConnectionAttempt);
                this._setTimeout(this.Id + "._verifyConnection()", 1000);
            } else {
                // fake that there was a control connection error by calling the handler
                this.controlConnectErrorHandler();
            }
        }
    }

    /// <summary>
    /// Callback method that polls the IsConnected property of the control to determine if the 
    /// connection is still active.  If it is not, the OnDisconnect event is raised.
    /// </summary>
    this._pollConnection = _pollConnection;
    function _pollConnection(){
        if(this.isConnected()){
            this._setTimeout(this.Id + "._pollConnection()", 1000);
        } else {
            // fake that there was a control disconnection by calling the handler
            this.controlDisconnectHandler();
        }
    }

    /// <summary>
    /// Method tells the TermClient to attempt to disconnect from the remote session.
    /// </summary>
    this.disconnect = _disconnect;
    function _disconnect(args) {
        try{
            this._control.Disconnect();
            log.info("[" + this.Id + "]:  VNCActiveXTermClient successfully disconnected from: " + this._hostURL);
        } catch (e){
            log.error("[" + this.Id + "]:  VNCActiveXTermClient suffered an error attempting to disconnect: " + e.message);
        }
    }

    /// <summary>
    /// Method renders the TermClient's HTML to the target frame's document.  The method 
    /// of render varies for each implementation.
    /// </summary>
    this.renderHtml = _renderHtml;
    function _renderHtml() {
        var ctlid = this.Id + this._ctlSuffix;
        var fullScreen = (TerminalClientSettings.EnableFullScreen)? 1 : 0;

        // since the citrix cab depends on the license manager, only attempt to load it if the
        //  license manager is installed...
        var isInstalled = true;
        try {
            var control = new ActiveXObject('License.Manager');
            control = null;
        } catch (e) {
            isInstalled = false;
        }

        var html = '<object classid="clsid:5220cb21-c88d-11cf-b347-00aa00a28331" viewastext="1">' +
                    '<param name="LPKPath" value="' + appPath + '/URA/lib/SCAX.lpk">' + 
                '</object>';
        if (isInstalled) {
            html = html +
                '<object id="' + ctlid + '"' + 
                    'classid="CLSID:62FA83F7-20EC-4D62-AC86-BAB705EE1CCD"' + 
                    'codebase="' + appPath + '/URA/lib/sviewerx_static.cab#version=2,5,86,2"' + 
                    'width="' + this.Width + '" height="' + this.Height + '"' + 
                    'style="padding:0px;margin:0px;" >' + 
                    '<param name="HostIP" value="' + this.HostAddress + '" />' + 
                    '<param name="Port" value="' + this.HostPort + '" />' + 
                    '<param name="Password" value="' + this.ProtocolPassword + '" />' + 
                    '<param name="CustomCompression" value="0" />' + 
                    '<param name="CustomCompressionLevel" value="6" />' + 
                    '<param name="JPEGCompression" value="1" />' + 
                    '<param name="JPEGCompressionLevel" value="6" />' + 
                    '<param name="CopyRect" value="1" />' + 
                    '<param name="EmulateThreeButton" value="1" />' + 
                    '<param name="SwapMouseButtons" value="0" />' + 
                    '<param name="Encoding" value="7" />' + 
                    '<param name="ViewOnly" value="0" />' + 
                    '<param name="RestrictPixel" value="0" />' + 
                    '<param name="ScaleNum" value="1" />' + 
                    '<param name="ScaleDen" value="1" />' + 
                    '<param name="ScaleEnable" value="0" />' + 
                    '<param name="FullScreen" value="' + fullScreen + '" />' + 
                    '<param name="Depth" value="' + TerminalClientSettings.ColorDepth + '" />' + 
                    '<param name="LocalCursor" value="1" />' + 
                    '<param name="MessageBoxes" value="1" />' + 
                    '<param name="DisableClipboard" value="0" />' + 
                    '<param name="DisconnectedText" value="" />' + 
                    '<param name="ConnectingText" value="" />' + 
                    '<param name="ThumbnailMode" value="0" />' + 
                    '<param name="LoginType" value="0" />' + 
                    '<param name="MsUser" value="" />' + 
                    '<param name="MsDomain" value="" />' + 
                    '<param name="ProxyIP" value="" />' + 
                    '<param name="ProxyPort" value="-1" />' + 
                    '<param name="ProxyUser" value="" />' + 
                    '<param name="ProxyPassword" value="" />' + 
                    '<param name="ProxyType" value="0" />' + 
                    '<param name="ConnectionBar" value="0" />' + 
                    '<param name="StretchMode" value="0" />' + 
                '</object>';
        }
        return html;
    }

    /// <summary>
    /// Method to send Ctrl+Alt+Delete to the TermClient control
    /// </summary>
    this.sendCtrlAltDelete = _sendCtrlAltDelete;
    function _sendCtrlAltDelete(){
        this._control.SendCAD();
    }

    /// <summary>
    /// Method to retrieve the key commands to send Ctrl+Alt+Delete to the TermClient control.
    /// </summary>
    this.getCADCommand = _getCADCommand;
    function _getCADCommand(){
        // send null because the key command is supported by the control
        return null;
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnConnect event.
    /// </summary>
    this.controlConnectHandler = _controlConnectHandler;
    function _controlConnectHandler(){
        log.info("[" + this.Id + "]:  VNCActiveXTermClient received connect event from the ActiveX control for: " + this._hostURL);
        // set the private switch to indicate that the connection has completed
        this._connectComplete = true;
        this.Width = this._control.ScreenWidth;
        this.Height = this._control.ScreenHeight;
        this._control.style.width = this.Width + "px";
        this._control.style.height = this.Height + "px";
        // raise the OnConnect event
        this._raiseEvent("OnConnect", null);
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnDisconnect event.
    /// </summary>
    this.controlDisconnectHandler = _controlDisconnectHandler;
    function _controlDisconnectHandler(){
        log.info("[" + this.Id + "]:  VNCActiveXTermClient successfully disconnected from: " + this._hostURL);
        // raise the OnDisconnect event
        this._raiseEvent("OnDisconnect", null);
        /*if(this._connectStarted){
            if(!this._connectComplete){
                // the control has attempted to connect, and has failed, so we raise the OnConnectError
                this.controlConnectErrorHandler();
            } else {
                // the control has attempted to connect, the connection has succeeded, so raise the OnDisconnect
                log.info("[" + this.Id + "]:  VNCActiveXTermClient received disconnect event from the ActiveX control for: " + this._hostURL);
                // raise the OnDisconnect event
                this._raiseEvent("OnDisconnect", null);
            }
        } else {
            log.info("[" + this.Id + "]:  VNCActiveXTermClient received disconnect event from the ActiveX control for: " + this._hostURL + 
                    " -- however the control had not yet started connection.  The event has been suppressed.");
        }*/
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnConnectError event.
    /// </summary>
    this.controlConnectErrorHandler = _controlConnectErrorHandler;
    function _controlConnectErrorHandler(){
        log.info("[" + this.Id + "]:  VNCActiveXTermClient received connect error event from the ActiveX control for: " + this._hostURL);
        // raise the OnConnectError event
        this._raiseEvent("OnConnectError", null);
    }

    /// <summary>
    /// Method gets the ActiveX or Applet control of the TermClient depending upon what 
    /// ControlPlatform has been deployed.
    /// </summary>
    /// <return type="object">the internal control, if this control has not been properly
    /// initialized this method ***can return null***</return>
    this.getControl = _getControl;
    function _getControl(){
        return this._control;
    }

    /// <summary>
    /// Method determines if the control is actually connected or not, helpful for polling 
    /// exercises and error checking in the URACoordinators.
    /// </summary>
    this.isConnected = _isConnected;
    function _isConnected(){
        if(typeof(this._control.GetConnectionState) != "undefined"){
            if(this._control.GetConnectionState() == 1){
                log.info("[" + this.Id + "]:  VNCActiveXTermClient.isConnected returned: true");
                return true;
            } else {
                log.info("[" + this.Id + "]:  VNCActiveXTermClient.isConnected returned: false");
                return false;
            }
        } else {
            log.info("[" + this.Id + "]:  VNCActiveXTermClient.isConnected returned: false");
            return false;
        }
    }
}
// register this instance with the TermClientFactory
termClientFactory.registerTermClient(ControlPlatform.ActiveX, TermClientType.VNC, "VNCActiveXTermClient");


/**********************************************************************
   $Author: greynold $
   $Date: 2007/06/01 15:35:40 $
   $Revision: 1.22 $


   Copyright 2001 - 2004. Surgient, Inc. All rights reserved. This 
   software code is an unpublished work and contains trade secrets of 
   Surgient, Inc. and is distributed only under license restrictions. No 
   part of this software code may be displayed, used, reproduced, stored 
   on a retrieval system, distributed, or transmitted without the 
   express written consent of Surgient, Inc. Violation of the provisions 
   contained herein may result in severe civil and criminal penalties, 
   and any violators will be prosecuted to the maximum extent possible 
   under the law. 
   
   "Surgient", "Virtualization Control Server" and "Surgient VCS" are 
   trademarks or registered trademarks of Surgient, Inc. in the United 
   States and foreign countries. 
**********************************************************************/

/// <summary>
/// Implementation class for the Citrix ActiveX TermClient object.
/// </summary>
/// <param name="id" type="string">the id of the TermClient instance</param>
function VNCJavaTermClient(id){
/// region : inheritance --------------------------------------------
    this.base = TermClient;
    this.base(id);
    log.info("[" + id + "]:  RDPActiveXTermClient object created.");

/// region : private fields -----------------------------------------
    this._ctlSuffix = "_ax";

/// region : private fields -----------------------------------------
    this._termClientType = TermClientType.Citrix;
    this._control = null; // holds a reference to the HTML element
    this._connectCount = 25; // counter for the number of permissable connection attempts

/// region : Properties ---------------------------------------------

    /// <summary>
    /// Gets/sets the Protocol for this object.
    /// </summary>
    this.Protocol = TermClientProtocol.VNC;

    /// <summary>
    /// Gets/sets the ControlPlatform for this object.
    /// </summary>
    this.Platform = ControlPlatform.Applet;

    /// <summary>
    /// Gets/sets the TermClientType for this object.
    /// </summary>
    this.TermClientType = TermClientType.VNC;

    /// <summary>
    /// Gets/sets the control's ScalingMode property.  See control ScalingMode docs.
    /// </summary>
    this.ScalingMode = 0;

    /// <summary>
    /// Gets/sets the control's Desired color depth property.  See control DesiredColor docs.
    /// </summary>
    this.DesiredColor = 16;

/// region : Methods ------------------------------------------------

    /// <summary>
    /// Method handles any initialization needed for the control before the connect() method 
    /// is called.  Not all controls will implement the init() method therefore this is not 
    /// a "virtual" method, just an empty stub that must be overridden for any effect to occur.
    /// </summary>
    /// <param name="args" type="object">initialization arguments, this is dependent upon implementation</param>
    this.init = _init;
    function _init(args){
        // no noop call here, if a control does not override, fail silently.
        return;
    }

    /// <summary>
    /// Method tells the TermClient to attempt to start the remote session. Raises 
    /// an OnConnect event.
    /// </summary>
    this.connect = _connect;
    function _connect(){        
        // create a counter for the number of connection attempts
        if(typeof(this._connectionAttempt) == "undefined"){
            this._connectionAttempt = 0;
        }

        try
        {
            // find our control and bind to it
            this._control = this.Element.getElementById(this.Id + this._ctlSuffix);
            if(this._control == null){
                log.error("[" + this.Id + "]:  VNCJavaTermClient unable to find rendered object tag in document.");
                throw this._newError("No download error.");
            }
            log.debug("[" + this.Id + "]:  VNCJavaTermClient._control = " + this._control);

            try
            {
                // if the control is null, throw an error so that the function is re-called.
            	if(this._control == null){
                    throw this._newError("Control not loaded.");
                }

                // the isConnected method is a simple boolean test, the results of which don't matter 
                // at this point, to verify that the control has been loaded properly this method just 
                // needs to return a value and not throw an exception because the method is not supported.
                if(this._control.isConnected() || !this._control.isConnected()){
                    log.info("[" + this.Id + "]:  VNCJavaTermClient preparing to connect.");
                    this._hostURL = this.Protocol + "://" + this.HostAddress + ":" + this.HostPort;
                    this._setTimeout(this.Id + "._verifyConnection()", 1000);
                }
            }
            catch (ex)
            {
                log.info("[" + this.Id + "]:  VNCJavaTermClient attempting connection:  " + this._connectionAttempt);
                if(this._connectionAttempt < this._connectCount){
                    this._connectionAttempt++;
                    this._setTimeout(this.Id + ".connect()", 1000);
                } else {
                    this._raiseEvent("OnLoadError", null);
                }
            }
        }
        catch (e)
        {
            if(e.message == "No download error."){
                log.fatal("[" + this.Id + "]:  VNCJavaTermClient control unable to initialize due to download or installation error.");
            } else {
                log.fatal("[" + this.Id + "]:  VNCJavaTermClient control suffered a fatal initialization error: " + e.message);
            }
            this._raiseEvent("OnConnectError", null);
        }
    }

    /// <summary>
    /// A polling method that will attempt to determine if the control has successfully 
    /// connected or not when the control does not support callback mechanisms for the connection event.
    /// </summary>
    this._verifyConnection = _verifyConnection;
    function _verifyConnection(){
        if(typeof(this._verifyConnectionAttempt) == "undefined"){
            this._verifyConnectionAttempt = 0;
        }
        if(this.isConnected()){
            // the control is connected so begin the connection polling process
            this._setTimeout(this.Id + "._pollConnection()", 1000);
            // fake that there was a control connection event by calling the handler
            this.controlConnectHandler();
        } else {
            if(this._verifyConnectionAttempt < this._connectCount){
                this._verifyConnectionAttempt++;
                log.info("[" + this.Id + "]:  VNCJavaTermClient attempting connection verification:  " + this._verifyConnectionAttempt);
                this._setTimeout(this.Id + "._verifyConnection()", 1000);
            } else {
                // fake that there was a control connection error by calling the handler
                this.controlConnectErrorHandler();
            }
        }
    }

    /// <summary>
    /// Callback method that polls the IsConnected property of the control to determine if the 
    /// connection is still active.  If it is not, the OnDisconnect event is raised.
    /// </summary>
    this._pollConnection = _pollConnection;
    function _pollConnection(){
        if(this.isConnected()){
            this._setTimeout(this.Id + "._pollConnection()", 1000);
        } else {
            // fake that there was a control disconnection by calling the handler
            this.controlDisconnectHandler();
        }
    }

    /// <summary>
    /// Method tells the TermClient to attempt to disconnect from the remote session.
    /// </summary>
    this.disconnect = _disconnect;
    function _disconnect(args) {
        try{
            this._control.disconnect();
            log.info("[" + this.Id + "]:  VNCJavaTermClient successfully disconnected from: " + this._hostURL);
        } catch (e){
            log.error("[" + this.Id + "]:  VNCJavaTermClient suffered an error attempting to disconnect: " + e.message);
        }
    }

    /// <summary>
    /// Method renders the TermClient's HTML to the target frame's document.  The method 
    /// of render varies for each implementation.
    /// </summary>
    this.renderHtml = _renderHtml;
    function _renderHtml() {
        var ctlid = this.Id + this._ctlSuffix;
        return '<applet id="' + ctlid + '" ' + 
                    'code="VncViewer.class" ' + 
                    'archive="' + appPath + '/URA/lib/VncViewer.jar" ' + 
                    'width="' + this.Width + '" height="' + this.Height + '" ' + 
                    'style="padding:0px;margin:0px;" >' + 
                    '<param name="cabbase" value="' + appPath + '/URA/lib/VncViewer11.cab">' + 
                    '<param name="HOST" value="' + this.HostAddress + '">' + 
                    '<param name="PORT" value="' + this.HostPort + '">' + 
                    '<param name="SHOW CONTROLS" value="no">' + 
                    '<param name="PASSWORD" value="' + this.ProtocolPassword + '" />' +
                    '<param name="CURSOR SHAPE UPDATES" value="Disable" />' +
                '</applet>';
    }

    /// <summary>
    /// Method to send Ctrl+Alt+Delete to the TermClient control
    /// </summary>
    this.sendCtrlAltDelete = _sendCtrlAltDelete;
    function _sendCtrlAltDelete(){
        this._control.sendCAD();
    }

    /// <summary>
    /// Method to retrieve the key commands to send Ctrl+Alt+Delete to the TermClient control.
    /// </summary>
    this.getCADCommand = _getCADCommand;
    function _getCADCommand(){
        // send null because the key command is supported by the control
        return null;
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnConnect event.
    /// </summary>
    this.controlConnectHandler = _controlConnectHandler;
    function _controlConnectHandler(){
        log.info("[" + this.Id + "]:  VNCJavaTermClient successfully connected to: " + this._hostURL);
        this.Width = this._control.getDesktopWidth();
        this.Height = this._control.getDesktopHeight();
        this._control.style.width = this.Width + "px";
        this._control.style.height = this.Height + "px";
        // raise the OnConnect event
        this._raiseEvent("OnConnect", null);
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnDisconnect event.
    /// </summary>
    this.controlDisconnectHandler = _controlDisconnectHandler;
    function _controlDisconnectHandler(){
        log.info("[" + this.Id + "]:  VNCJavaTermClient successfully disconnected from: " + this._hostURL);
        // raise the OnDisconnect event
        this._raiseEvent("OnDisconnect", null);
    }

    /// <summary>
    /// Callback event handler for the TermClient control if it supports the OnConnectError event.
    /// </summary>
    this.controlConnectErrorHandler = _controlConnectErrorHandler;
    function _controlConnectErrorHandler(){
        log.info("[" + this.Id + "]:  VNCJavaTermClient failed to connect to: " + this._hostURL);
        // raise the OnConnectError event
        this._raiseEvent("OnConnectError", null);
    }

    /// <summary>
    /// Method gets the ActiveX or Applet control of the TermClient depending upon what 
    /// ControlPlatform has been deployed.
    /// </summary>
    /// <return type="object">the internal control, if this control has not been properly
    /// initialized this method ***can return null***</return>
    this.getControl = _getControl;
    function _getControl(){
        return this._control;
    }

    /// <summary>
    /// Method determines if the control is actually connected or not, helpful for polling 
    /// exercises and error checking in the URACoordinators.
    /// </summary>
    this.isConnected = _isConnected;
    function _isConnected(){
        try
        {
            if(this._control.isConnected()){
                log.info("[" + this.Id + "]:  VNCJavaTermClient.isConnected returned: true");
                return true;
            } else {
                log.info("[" + this.Id + "]:  VNCJavaTermClient.isConnected returned: false");
                return false;
            }
        }
        catch (e)
        {
            log.info("[" + this.Id + "]:  VNCJavaTermClient.isConnected returned: false");
            return false;
        }
    }
}
// register this instance with the TermClientFactory
termClientFactory.registerTermClient(ControlPlatform.Applet, TermClientType.VNC, "VNCJavaTermClient");


