| //////////////////////////////////////////////////////////////////////////////// |
| // |
| // Licensed to the Apache Software Foundation (ASF) under one or more |
| // contributor license agreements. See the NOTICE file distributed with |
| // this work for additional information regarding copyright ownership. |
| // The ASF licenses this file to You under the Apache License, Version 2.0 |
| // (the "License"); you may not use this file except in compliance with |
| // the License. You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| //////////////////////////////////////////////////////////////////////////////// |
| package mx.automation.tool |
| { |
| import flash.display.Sprite; |
| import flash.events.Event; |
| import flash.utils.Timer; |
| |
| import mx.automation.AutomationHelper; |
| import mx.core.Application; |
| import mx.core.FlexGlobals; |
| import mx.core.UIComponent; |
| |
| public class ClientSocketHandler extends Sprite |
| { |
| |
| private static var socket:CustomSocket; |
| private static var currentToolAdapter:ToolAdapter; |
| |
| private var currentDataFromAppToAgent:ApplicationDataToAgent; |
| private var isInPartDataProcessing:Boolean; |
| |
| private var recordRequestsQueue:Array; // array of request data to be processed one after the other. |
| // this is to ensure that data will be sent synchronously one after the other. |
| // please note that in such cases we should not expect request back from the client. (other than |
| // for the incomplete processing. |
| // if we expect so, we need to figure out some other methods. // like we can indicate proceed to next only |
| // after recieveing an x data request from app. |
| |
| |
| private var count:int = 0; private var currentApplicationId:String; |
| private var applicationType:int; |
| |
| private var requestsSent:Array = new Array(); // for debugging... |
| // later may be we can remove this. |
| |
| private var responsesRecieved:Array = new Array(); // for debugging... |
| // later may be we can remove this. |
| |
| |
| // receiving data from Agent |
| private var currentDataFromAgent:Array = new Array(); |
| private static var insideIncompleteLoop:Boolean = false; |
| private var isInRecording:Boolean = false; |
| private var isToolInRecordingStatus:Boolean = false; |
| private var isToolInRunningStatus:Boolean = false; |
| |
| |
| |
| public static const separator:String = "|"; |
| private static const portNo:int = 2000; |
| |
| public static const dataEndIndicator:String = "__DATA_FROM_TOOL_AGENT__END__"; |
| public static const dataPartIndicator:String ="__DATA_FROM_TOOL_AGENT_PART__"; |
| |
| public static const dataToAgentEndIndicator:String = "__DATA_TO_TOOL_AGENT__END__"; |
| public static const dataToAgentPartIndicator:String ="__DATA_TO_TOOL_AGENT_PART__"; |
| |
| public static const dataStatusIndicatorLen:int = dataEndIndicator.length; |
| public static const requestToCompletePrev:String= "-CompletePrevious"; |
| |
| // both the end and the part string length should be the same |
| |
| // to agent strings |
| public static const startRequestString:String = "Start"; |
| public static const closeRequestString:String = "CloseSocket"; |
| public static const envRequestString:String = "ReqEnv"; |
| public static const recordRequestString:String = "Record"; |
| public static const activeScreenDataStoreRequestString:String = "StoreActiveScreen"; |
| public static const acceptApplicationBoundaryInScreenCoordinates:String = "AcceptAppBoundaryInScreenCoords"; |
| |
| // from agent strings |
| public static const nullValueIndicator:String= "__MX_NULL__"; |
| public static const emptyStringIndicator:String= "__MX_EMPTY_STRING__"; |
| |
| public static const socketStarted:String = "SocketStarted"; |
| public static const socketAccepted:String = "SocketAccepted"; |
| |
| public static const beginRecordInstructionString:String = "BeginRecording"; |
| public static const endRecordInstructionString:String = "EndRecording"; |
| |
| |
| public static const startRunInstructionString:String = "StartRunning"; |
| public static const endRunInstructionString:String = "EndRunning"; |
| |
| public static const setEnvInstructionString:String = "SetEnv"; |
| public static const sendRecordDetails:String = "SendRecordDetails"; |
| public static const finishedRecordIndicator:String = "FinishedRecordIndicator"; |
| public static const captureHandle:String = "CaptureWindowHandle"; |
| public static const captureHandleForNewWindow:String = "CaptureWindowHandleForNewWindow"; |
| public static const handleForNewWindowCaptured:String = "HandleForNewWindowCaptured"; |
| public static const getNewWindowDetails:String = "GetNewWindowDetails"; |
| public static const noNewWindow:String = "NoNewWindowCreatedDuringLastRun"; |
| |
| public static const isPointInside:String = "IsPointInside"; |
| public static const getElementFromPoint:String = "GetElementFromPoint"; |
| public static const getObjectType:String = "GetObjectType"; |
| public static const getParent:String = "GetParent"; |
| public static const getChildren:String = "GetChildren"; |
| public static const childrenSeparator:String = ":|:"; |
| public static const learnChildren:String = "LearnChildren"; |
| public static const leanrnChildrenIdXMLSeparator:String = "__ID_XML_SEP__"; |
| public static const leanrnChildrenIdsSeparator:String = "__IDS_SEP__"; |
| |
| public static const getDisplayName:String = "GetDisplayName"; |
| public static const getProperties:String = "GetProperties"; |
| public static const getProperties_ValueSeparator:String = "__MX_ARG_SEP__"; |
| public static const eventArgsSeparator:String = "__MX_EVNET_ARG_SEP__"; |
| public static const typeValueSeparator:String = "__MX_TYPE_VAL_SEP__"; |
| public static const recordInfoSeparator:String = "__MX_RECORD_INFO_SEP__"; |
| public static const recordNoArgIndicator:String = "FOR_TOOL_NO_ARGS_FROM_APP"; |
| public static const buildDescription:String = "BuildDescription"; |
| |
| public static const getTabularData:String = "GetTabularData"; |
| public static const getTabularDataArgSeparator:String = "__TABULAR_DATA_ARGS_SEP__"; |
| public static const getTabularData_Title_Table_Separator:String = "__TITLE_TABLE_DATA_SEP__"; |
| public static const getTabularData_Title_Data_Separator:String = "__TITLE_DATA_SEP__"; |
| public static const getTabularData_Table_Data_Separator:String = "__TABLE_DATA_SEP__"; |
| public static const getTabularAttributes:String = "GetTabularAttributes"; |
| |
| |
| public static const findObjectId:String = "FindObjectId"; |
| public static const findObjectId2:String = "FindObjectId2"; |
| public static const compareObjectIds:String = "CompareObjectIds"; |
| public static const objectIdSeparators:String = ":|:"; |
| |
| |
| public static const getRectangle:String = "GetRectangle"; |
| public static const rectangeInfoSeparator:String = ","; |
| |
| public static const run:String = "Run"; |
| public static const runParamSeparator:String = "__RUN_PARAM_SEP__"; |
| public static const getLastError:String="GetLastError"; |
| |
| |
| |
| public static const falseString:String = "Ret_False"; |
| public static const trueString:String = "Ret_True"; |
| |
| public static const idNamesSeparator:String = "__MX_ID_NAME_SEP__"; |
| public static const idFilterSeparator:String = "__MX_ID_FILT_SEP__"; |
| |
| public static const toAppDataMaxLength:int = 2500; |
| |
| |
| public static const appTypeAir:String = "Air"; |
| public static const appTypeFlex:String = "Flex"; |
| |
| private var tempCount:int = 0; |
| |
| private static var appAlpha:int = -1; |
| private var isInRunning :Boolean = false; |
| |
| public function ClientSocketHandler(adapter:ToolAdapter, currentAppId:String, appType:int ) |
| { |
| // create the client socket and request for connection. |
| |
| //store the application ID. we need this to be sent with every message. |
| currentApplicationId = currentAppId; |
| currentToolAdapter = adapter; |
| applicationType = appType; |
| |
| disableApplication(); |
| |
| ToolAdapter.showConnectionAttemptMessage(); |
| |
| // create a new socket and the port |
| socket = new CustomSocket("localhost", ClientSocketHandler.portNo); |
| socket.addEventListener(SocketResponseEvent.SOCKET_RESPONSE,responseHandler); |
| //socket.addEventListener(SocketResponseEvent.SOCKET_RESPONSE,RecordingHandler.handleResponse); |
| |
| var tempTimer:Timer = new Timer(5000,3); |
| tempTimer.addEventListener("timer", checkForConnection); |
| tempTimer.start(); |
| |
| |
| |
| } |
| |
| private static var _isDisabled:Boolean = false; |
| |
| public static function disableApplication():void |
| { |
| var appObj:UIComponent = FlexGlobals.topLevelApplication as UIComponent; |
| if(appObj) |
| { |
| // we need to handle all window disabling |
| appAlpha = appObj.alpha; |
| appObj.alpha= .4; |
| appObj.enabled = false; |
| _isDisabled = true; |
| } |
| } |
| |
| public static function enableApplication():void |
| { |
| if(_isDisabled) |
| { |
| var appObj:UIComponent = FlexGlobals.topLevelApplication as UIComponent; |
| if(appObj) |
| { |
| appObj.alpha= appAlpha; |
| appObj.enabled = true; |
| _isDisabled = false; |
| } |
| } |
| } |
| |
| public function addToRecordRequestQueue(requestObject:Object):int //Object of type RequestData |
| //Change for marshalling |
| { |
| |
| // this is to handle the multiple requests which needs to be |
| // processed for the record operation. |
| if( !recordRequestsQueue) |
| recordRequestsQueue = new Array(); |
| |
| return recordRequestsQueue.push(requestObject); |
| |
| } |
| |
| public function processQueuedRecordRequests(fromAgent:Boolean = false):Boolean |
| { |
| |
| var processed:Boolean = false; |
| if(fromAgent == true) |
| { |
| // process only if we are fresh in the list |
| // i.e only if we are not in the record processing |
| if((isInRecording == true)||(isInPartDataProcessing == true)) |
| { |
| //trace (" not processing the request from agent"); |
| return false; |
| } |
| |
| } |
| // this will send the stored erquest in order |
| // this will be called first from the recordHandler of the qtp and |
| // then once we get the record request back from the agent. |
| |
| |
| // it is quite possible that another record information got added to the queue |
| // when we were processing with the previous one. |
| // but we should not process this |
| // instead let the record processing mechanism to handle this |
| if(isInPartDataProcessing == false) |
| { |
| /* |
| if(fromAgent == true) |
| trace ("processing request from agent"); |
| else |
| trace ("processing request from end record info");*/ |
| |
| |
| if((recordRequestsQueue) && (recordRequestsQueue.length)) |
| { |
| isInRecording = true; |
| // we need to remove the elements in the order they were added. |
| //currentRequest is of type RequestData. Changed to Object to support Marshalling |
| var currentRequest:Object = recordRequestsQueue.shift(); |
| sendData(currentRequest.requestID, currentRequest.requestData); |
| |
| processed = true; |
| } |
| } |
| |
| return processed; |
| } |
| |
| private function getResponseDetails(responseString:String):Array |
| { |
| var details:Array = new Array(); |
| |
| // every response will have the following format |
| // id of the application|responseIdentifier|Response. |
| // get the application identifier. |
| // we need not blindly use split as there may be the same devider in the |
| // data part also. Hence read the tokens separately as we are interested only in the |
| // first two tokens. |
| var index:int = responseString.indexOf(ClientSocketHandler.separator); |
| var applicationId:String; |
| if(index > -1) |
| { |
| // get the applicationid |
| applicationId = responseString.substring(0,index); |
| } |
| |
| // proceed only if the current application id matches. |
| // this is just to ensure that we dont process the response sent to other application |
| // by mistake. (eventhough care will be taken from the server to send to the correct applicaiton) |
| if((applicationId) && (applicationId == currentApplicationId)) |
| { |
| |
| details.push(applicationId); |
| // get the response identifier |
| var index1:int = responseString.indexOf(ClientSocketHandler.separator,index+1); |
| if(index1 > -1) |
| { |
| // get the applicationid |
| var responseIdentifier:String = responseString.substring(index+1,index1); |
| details.push(responseIdentifier); |
| |
| // get the data |
| var index2:int = responseString.lastIndexOf(ClientSocketHandler.separator); |
| if(index2 > -1) |
| { |
| // get the data |
| var responseData:String = responseString.substring(index1+1,index2); |
| details.push(responseData); |
| |
| // get the response status indicator |
| var statusIndicator:String = responseString.substr(index2+1, responseString.length- (index2+1)); |
| details.push(statusIndicator); |
| |
| } |
| |
| } |
| } |
| |
| return details; |
| |
| } |
| |
| |
| |
| |
| private function combineCurrentData(currentData:Array):void |
| { |
| //if the current is not empty, then assign new |
| // else check all fields, and combine the data string - 3rd entry in the array |
| if(currentDataFromAgent && currentDataFromAgent.length==4 ) |
| { |
| // check whether all the data matches |
| // TBD validity check |
| var dataString:String = currentDataFromAgent[2]; |
| dataString = dataString + currentData[2]; |
| |
| currentDataFromAgent[2] = dataString ; |
| //trace (currentData[2]); |
| } |
| else |
| { |
| currentDataFromAgent = new Array(); |
| |
| currentDataFromAgent = currentData; |
| } |
| |
| |
| } |
| |
| private function clearCurrentData():void |
| { |
| currentDataFromAgent = new Array(); |
| } |
| |
| private var socketAccepted:Boolean = false; |
| private var connectionTrialCount:int = 0; |
| |
| private function checkForConnection(event:Event):void |
| { |
| connectionTrialCount ++; |
| if(connectionTrialCount == 3) |
| { |
| if (!socketAccepted) |
| { |
| ToolAdapter.showConnectionFailureMessage(); |
| } |
| } |
| } |
| |
| public function responseHandler(event:SocketResponseEvent):void |
| { |
| // dont process the request unless the air libraries are loaded |
| // properly |
| if(!AutomationHelper.isAirClassLoaded()) |
| return; |
| |
| // we need to process here only if the current response is not |
| // from recording |
| /* |
| if(event.isInRecordProcessing) |
| return ;*/ |
| |
| //dispatchEvent(new SocketResponseEvent(event.response,event.type)); |
| //trace ("from event"+ event.response); |
| // [0] - appID , [1] - Indentifier , [2] - Data |
| |
| if(event.response.length == 0) |
| { |
| |
| // we got the empty response. |
| // this happens after sending data and we dont get any response back from the applicaiton |
| // but this can be used to trigger the queded requests. |
| |
| if(isInPartDataProcessing == false) |
| { |
| // if we have some queued request process that. |
| //processQueuedRequests(); |
| } |
| } |
| else |
| { |
| |
| var responseDetails:Array = getResponseDetails(event.response); |
| |
| var responseString:String; |
| var processCurrentData:Boolean = false; |
| |
| if((responseDetails) && (responseDetails.length > 1)) |
| responseString = responseDetails[1]; |
| |
| if(responseString) |
| { |
| // check whether it is request for the part data completion |
| if(responseString.indexOf(ClientSocketHandler.requestToCompletePrev) != -1) |
| { |
| // this indicates that we are in the part processing |
| if(isInPartDataProcessing == false) |
| { |
| // this indicates programming or synchronisation error. |
| // ignore this |
| var a_nFalseExecution:int = 1; |
| trace ("ClientSocketHandler:responseHandler()-"+event.response); |
| trace ("ClientSocketHandler:responseHandler()-We should not have come here .... " + responseString); |
| } |
| else |
| { |
| // separate the actual string |
| responseString = responseString.substr(0,responseString.length-ClientSocketHandler.requestToCompletePrev.length); |
| sendCurrentPartData(responseString); |
| } |
| } |
| else |
| { |
| |
| if(isInPartDataProcessing == true) |
| { |
| trace ("ClientSocketHandler:responseHandler()-"+event.response); |
| trace ("ClientSocketHandler:responseHandler()- We should not have come here 2.... " + responseString); |
| } |
| // we have not recieved to send the previous incomplete information continuation. |
| // i.e the data recieved is for us to use and handle |
| // now check whether this data is complete or part |
| // check the status of the message |
| if(responseDetails.length > 3) |
| { |
| var statusIndicator:String = responseDetails[3]; |
| |
| // combine the current data with the existing |
| combineCurrentData(responseDetails); |
| |
| if(statusIndicator == dataEndIndicator) |
| { |
| insideIncompleteLoop = false; |
| processCurrentData = true; |
| } |
| else |
| { |
| insideIncompleteLoop = true; |
| processCurrentData = false; |
| } |
| } |
| |
| if(insideIncompleteLoop) |
| { |
| tempCount++; |
| // current dat is incomplete |
| // send request for the next set |
| sendData(currentDataFromAgent[1]+ClientSocketHandler.requestToCompletePrev); |
| } |
| else if(responseString && processCurrentData) |
| { |
| tempCount = 0; |
| |
| if(responseString == ClientSocketHandler.socketStarted) |
| { |
| // request the env details |
| sendData(ClientSocketHandler.startRequestString); |
| //tempTimer. |
| |
| } |
| // process the current data |
| else if(responseString == ClientSocketHandler.socketAccepted) |
| { |
| socketAccepted = true; |
| // request the env details |
| sendData(ClientSocketHandler.envRequestString); |
| |
| } |
| else if (responseString == ClientSocketHandler.handleForNewWindowCaptured) |
| { |
| ClientSocketHandler.isNewWindowRegistrationOver = true; |
| sendData(ClientSocketHandler.handleForNewWindowCaptured,""); |
| } |
| |
| else if(responseString == ClientSocketHandler.beginRecordInstructionString) |
| { |
| // start recording. |
| currentToolAdapter.beginRecording(); |
| isToolInRecordingStatus = true; |
| |
| |
| } |
| else if(responseString == ClientSocketHandler.endRecordInstructionString) |
| { |
| //end recording |
| currentToolAdapter.endRecording(); |
| isToolInRecordingStatus = false; |
| |
| } |
| else if(responseString == ClientSocketHandler.startRunInstructionString) |
| { |
| //end recording |
| isToolInRunningStatus = true; |
| } |
| else if(responseString == ClientSocketHandler.endRunInstructionString) |
| { |
| //end recording |
| isToolInRunningStatus = false; |
| } |
| else if(responseString == ClientSocketHandler.setEnvInstructionString) |
| { |
| if(responseDetails[2]) |
| currentToolAdapter.setTestingEnvironment(currentDataFromAgent[2]); |
| |
| // get the App Title |
| var appTitle:String = currentToolAdapter.getAppTitle(); |
| //trace ("App Title " + appTitle); |
| // send the request to capture the window handle |
| |
| enableApplication(); |
| ToolAdapter.showConnectionSuccessMessage(); |
| sendData(ClientSocketHandler.captureHandle, appTitle); |
| |
| } |
| else if(responseString == ClientSocketHandler.sendRecordDetails) |
| { |
| //trace ("calling processQueuedRecordRequests sendRecordDetails"); |
| // request to send the stored record information |
| processQueuedRecordRequests(); |
| } |
| else if(responseString == ClientSocketHandler.finishedRecordIndicator) |
| { |
| //trace ("calling processQueuedRecordRequests finishedRecordIndicator"); |
| |
| // if there are fresh record requests in the queue |
| // this will process that |
| // request to send the stored record information if any |
| if(recordRequestsQueue.length == 0) |
| { |
| isInRecording = false; |
| // during recording if the previos operation has |
| // resulted in a new window creation we need to process |
| // the same after the current recording is over. |
| processNewWindowRequestToTool(); |
| } |
| else |
| processQueuedRecordRequests(); |
| } |
| /* .. is pointinside is not called from plugin |
| plugin does a diff way of finding whehter the point belongs to the application |
| else if(responseString == ClientSocketHandler.isPointInside) |
| { |
| var dataToBeSent:String = ClientSocketHandler.falseString; |
| |
| if(currentDataFromAgent[2]) |
| { |
| var pointArray:Array = (currentDataFromAgent[2] as String).split(","); |
| var windowId:String; |
| if(pointArray.length == 3) |
| windowId = pointArray[2]; |
| if(pointArray.length >= 2) |
| { |
| var checkPoint:Point = new Point(pointArray[0], pointArray[1]); |
| var status:Boolean = currentToolAdapter.isScreenPointWithinStageBoundary(checkPoint,windowId); |
| if(status) |
| dataToBeSent = ClientSocketHandler.trueString; |
| } |
| |
| } |
| sendData(ClientSocketHandler.isPointInside, dataToBeSent); |
| |
| } |
| */ |
| else if(responseString == ClientSocketHandler.getElementFromPoint) |
| { |
| |
| var dataToBeSent1:String = ""; |
| if(currentDataFromAgent[2]) |
| { |
| var pointArray1:Array = (currentDataFromAgent[2] as String).split(","); |
| var object:Object = null; |
| if(pointArray1.length == 2) |
| object = currentToolAdapter.getElementFromPoint(pointArray1[0], pointArray1[1], ""); |
| else if(pointArray1.length == 3) |
| object = currentToolAdapter.getElementFromPoint(pointArray1[0], pointArray1[1],pointArray1[2] ); |
| |
| dataToBeSent1 = object["result"]; |
| |
| } |
| sendData(ClientSocketHandler.getElementFromPoint,dataToBeSent1 ); |
| } |
| else if(responseString == ClientSocketHandler.getObjectType) |
| { |
| var dataToBeSent2:String = ""; |
| var objectId:String = currentDataFromAgent[2]; |
| if(objectId) |
| { |
| var object2:Object = currentToolAdapter.getElementType(objectId); |
| dataToBeSent2 = object2["result"]; |
| } |
| sendData(ClientSocketHandler.getObjectType,dataToBeSent2 ); |
| } |
| else if(responseString == ClientSocketHandler.getParent) |
| { |
| var dataToBeSent3:String = ""; |
| var objectId2:String = currentDataFromAgent[2]; |
| if(objectId2) |
| { |
| var object3:Object = currentToolAdapter.getParent(objectId2); |
| dataToBeSent3 = object3["result"]; |
| } |
| sendData(ClientSocketHandler.getParent,dataToBeSent3 ); |
| } |
| else if(responseString == ClientSocketHandler.getDisplayName) |
| { |
| var dataToBeSent4:String = ""; |
| var objectId3:String = currentDataFromAgent[2]; |
| if(objectId3) |
| { |
| var object4:Object = currentToolAdapter.getDisplayName(objectId3); |
| dataToBeSent4 = object4["result"]; |
| } |
| sendData(ClientSocketHandler.getDisplayName,dataToBeSent4 ); |
| } |
| else if(responseString == ClientSocketHandler.getProperties) |
| { |
| var dataToBeSent5:String = ""; |
| var idAndNames:String = currentDataFromAgent[2]; |
| if(idAndNames) |
| { |
| // separate the idAndNames |
| var idAndNamesArray:Array = idAndNames.split(ClientSocketHandler.idNamesSeparator); |
| if(idAndNamesArray.length == 2) |
| { |
| var objectID5:String = idAndNamesArray[0]; |
| var names:String = idAndNamesArray[1]; |
| //trace("Properties requested for " + names); |
| |
| var object5:Object = currentToolAdapter.getProperties(objectID5,names); |
| var dataObjectArray:Array = object5["result"] as Array; |
| if(dataObjectArray) |
| dataToBeSent5 = dataObjectArray.join(ClientSocketHandler.getProperties_ValueSeparator); |
| |
| } |
| } |
| sendData(ClientSocketHandler.getProperties,dataToBeSent5 ); |
| } |
| else if(responseString == ClientSocketHandler.getRectangle) |
| { |
| var dataToBeSent6:String = ""; |
| var objectID6:String = currentDataFromAgent[2]; |
| if(objectID6) |
| { |
| var arr1:Array = currentToolAdapter.getRectangleInScreenCoordinates(objectID6); |
| dataToBeSent6 = arr1.join(ClientSocketHandler.rectangeInfoSeparator); |
| } |
| sendData(ClientSocketHandler.getRectangle,dataToBeSent6 ); |
| } |
| |
| else if(responseString == ClientSocketHandler.buildDescription) |
| { |
| var dataToBeSent7String:String = ""; |
| var objectID7:String = currentDataFromAgent[2]; |
| if(objectID7) |
| { |
| var object7:Object = currentToolAdapter.buildDescription(objectID7); |
| dataToBeSent7String = object7["result"]; |
| |
| } |
| sendData(ClientSocketHandler.buildDescription,dataToBeSent7String ); |
| } |
| else if(responseString == ClientSocketHandler.getChildren) |
| { |
| var dataToBeSent8:String = ""; |
| var objectID_And_Filter:String = currentDataFromAgent[2]; |
| if(objectID_And_Filter) |
| { |
| // separate the idAndNames |
| var objectID_And_FilterArray:Array = objectID_And_Filter.split(ClientSocketHandler.idFilterSeparator); |
| if(objectID_And_FilterArray.length == 2) |
| { |
| var objectID8:String = objectID_And_FilterArray[0]; |
| var filter:String = objectID_And_FilterArray[1]; |
| |
| var object8:Object = currentToolAdapter.getChildren(objectID8,filter); |
| var dataToBeSentArray8:Array = (object8["result"] as Array); |
| dataToBeSent8 = dataToBeSentArray8.join(ClientSocketHandler.childrenSeparator); |
| } |
| } |
| sendData(ClientSocketHandler.getChildren,dataToBeSent8 ); |
| } |
| else if(responseString == ClientSocketHandler.learnChildren) |
| { |
| var dataToBeSent9:String = ""; |
| var objectID_And_Filter1:String = currentDataFromAgent[2]; |
| if(objectID_And_Filter1) |
| { |
| // separate the idAndNames |
| var objectID_And_FilterArray1:Array = objectID_And_Filter1.split(ClientSocketHandler.idFilterSeparator); |
| if(objectID_And_FilterArray1.length == 2) |
| { |
| var objectID9:String = objectID_And_FilterArray1[0]; |
| var filter1:String = objectID_And_FilterArray1[1]; |
| |
| var object9:Object = currentToolAdapter.learnChildObjects(objectID9,filter1); |
| var dataobject9:Object = (object9["result"]); |
| |
| var dataToBeSentArray9:Array = new Array(); |
| dataToBeSentArray9.push(dataobject9["learnChildrenXML"]); |
| var childIDs:Array = (dataobject9["childrenIDs"] as Array) |
| dataToBeSentArray9.push( childIDs.join(ClientSocketHandler.leanrnChildrenIdsSeparator)); |
| dataToBeSent9 = dataToBeSentArray9.join(ClientSocketHandler.leanrnChildrenIdXMLSeparator); |
| } |
| } |
| sendData(ClientSocketHandler.learnChildren,dataToBeSent9); |
| } |
| |
| else if(responseString == ClientSocketHandler.run) |
| { |
| |
| isInRunning = true; |
| var dataToBeSent10:String = ""; |
| var objectID_Method_Arg_String:String = currentDataFromAgent[2]; |
| |
| if(objectID_Method_Arg_String) |
| { |
| // separate the idAndNames |
| var objectID_Method_Arg_Array:Array = objectID_Method_Arg_String.split(ClientSocketHandler.runParamSeparator); |
| if(objectID_Method_Arg_Array.length == 3) |
| { |
| |
| var objectID10:String = objectID_Method_Arg_Array[0]; |
| //trace (objectID10); |
| var method:String = objectID_Method_Arg_Array[1]; |
| var args:String = objectID_Method_Arg_Array[2]; |
| |
| var object10:Object = currentToolAdapter.run(objectID10,method,args); |
| |
| dataToBeSent10 = ""; |
| if(object10) |
| { |
| var resultObj10:Object =(object10["result"]); |
| if(resultObj10) |
| dataToBeSent10 = resultObj10["type"] + ClientSocketHandler.runParamSeparator+(resultObj10["value"]); |
| } |
| } |
| } |
| sendData(ClientSocketHandler.run,dataToBeSent10); |
| // we need to set it false only after we sending the |
| // new window processing |
| //isInRunning = false; |
| //processNewWindowRequestToTool(); |
| } |
| else if(responseString == ClientSocketHandler.getLastError) |
| { |
| var dataToBeSent11:String = ""; |
| |
| var object11:Object = currentToolAdapter.getLastError(); |
| dataToBeSent11 = (object11["result"]); |
| sendData(ClientSocketHandler.getLastError,dataToBeSent11); |
| } |
| |
| else if(responseString == ClientSocketHandler.getTabularData) |
| { |
| var dataToBeSent12:String = ""; |
| |
| var tabularDataArgs:String = currentDataFromAgent[2]; |
| if(tabularDataArgs) |
| { |
| // separate the idAndNames |
| var tabularDataArgsArray:Array = tabularDataArgs.split(ClientSocketHandler.getTabularDataArgSeparator); |
| if(tabularDataArgsArray.length == 3) |
| { |
| var objectID12:String = tabularDataArgsArray[0]; |
| var min:Number = Number(tabularDataArgsArray[1]); |
| var max:Number = Number(tabularDataArgsArray[2]); |
| |
| var object12:Object = currentToolAdapter.getTabularData(objectID12,min,max); |
| var dataobject12:Object = (object12["result"]); |
| |
| var dataToBeSentArray12:Array = new Array(); |
| |
| // Creating a dummy object to handle error in unusual cases like |
| // object being visible only at the time of inserting checkpoint |
| // but not being available before that. |
| // Ex: Volume bar in Spark Mutebutton control. |
| // It will not be visible before we click on insert checkpoint |
| // It can be made visible later by clicking on Ctrl. |
| // If it is visible before we click on insert checkpoint |
| // it will not be available in the child list of the application |
| // by the time we come back to the application. |
| // http://bugs.adobe.com/jira/browse/FLEXENT-1113 |
| if(!dataobject12) |
| { |
| dataobject12 = new Object(); |
| dataobject12["columnTitles"] = new Array(); |
| dataobject12["tableData"] = new Array(); |
| } |
| |
| var columnNamesString:String = (dataobject12["columnTitles"] as Array).join(ClientSocketHandler.getTabularData_Title_Data_Separator); |
| if(columnNamesString=="") |
| { |
| if((dataobject12["columnTitles"] as Array).length == 0) |
| columnNamesString = ClientSocketHandler.nullValueIndicator; |
| else |
| columnNamesString = ClientSocketHandler.emptyStringIndicator; |
| } |
| dataToBeSentArray12.push(columnNamesString); |
| var tableDataString:String = openArrayOfArrays(dataobject12["tableData"] as Array, ClientSocketHandler.getTabularData_Table_Data_Separator) |
| //var tableDataString:String = (dataobject12["tableData"] as Array).join(ClientSocketHandler.getTabularData_Table_Data_Separator); |
| if(tableDataString=="") |
| { |
| if((dataobject12["tableData"] as Array).length == 0) |
| tableDataString = ClientSocketHandler.nullValueIndicator; |
| else |
| tableDataString = ClientSocketHandler.emptyStringIndicator; |
| } |
| |
| dataToBeSentArray12.push(tableDataString); |
| dataToBeSent12 = dataToBeSentArray12.join(ClientSocketHandler.getTabularData_Title_Table_Separator); |
| } |
| } |
| sendData(ClientSocketHandler.getTabularData,dataToBeSent12); |
| } |
| else if(responseString == ClientSocketHandler.getTabularAttributes) |
| { |
| var dataToBeSent13:String = ""; |
| |
| var objectID13:String = currentDataFromAgent[2]; |
| if(objectID13) |
| { |
| // separate the idAndNames |
| var object13:Object = currentToolAdapter.getTabularAttributes(objectID13); |
| var dataobject13:Object = (object13["result"]); |
| |
| var dataToBeSentArray13:Array = new Array(); |
| if(dataobject13) |
| { |
| dataToBeSentArray13.push(dataobject13["fullSize"]); |
| dataToBeSentArray13.push(dataobject13["minVisibleRow"]); |
| dataToBeSentArray13.push(dataobject13["maxVisibleRow"]); |
| } |
| else |
| { |
| // Creating a dummy array to handle error in unusual cases like |
| // object being visible only at the time of inserting checkpoint |
| // but not being available before that. |
| // Ex: Volume bar in Spark Mutebutton control. |
| // It will not be visible before we click on insert checkpoint |
| // It can be made visible later by clicking on Ctrl. |
| // If it is visible before we click on insert checkpoint |
| // it will not be available in the child list of the application |
| // by the time we come back to the application. |
| // http://bugs.adobe.com/jira/browse/FLEXENT-1113 |
| dataToBeSentArray13.push(0); |
| dataToBeSentArray13.push(0); |
| dataToBeSentArray13.push(0); |
| } |
| dataToBeSent13 = dataToBeSentArray13.toString(); // we are using the normal array sep |
| } |
| sendData(ClientSocketHandler.getTabularAttributes,dataToBeSent13); |
| } |
| else if(responseString == ClientSocketHandler.findObjectId2) |
| { |
| var dataToBeSent14:String = ""; |
| |
| var descriptionXml14:String = currentDataFromAgent[2]; |
| if(descriptionXml14) |
| { |
| // separate the idAndNames |
| var object14:Object = currentToolAdapter.findObjectIDs(descriptionXml14); |
| var dataobject14:Array = (object14["result"] as Array); |
| |
| if(dataobject14) |
| dataToBeSent14 = dataobject14.join(ClientSocketHandler.objectIdSeparators); |
| |
| } |
| sendData(ClientSocketHandler.findObjectId2,dataToBeSent14); |
| } |
| else if(responseString == ClientSocketHandler.getNewWindowDetails) |
| { |
| processNewWindowRequestToTool(null,ClientSocketHandler.getNewWindowDetails,true); |
| // WE would have got this request as a part of a run |
| // refer the plugin run handling code. |
| // so only after we processing this request we need to set the flag to false. |
| if(isInRunning) |
| isInRunning = false; |
| } |
| //getLastError |
| clearCurrentData(); |
| } |
| } |
| } |
| else |
| { |
| trace ("event response is not normal" + event.response); |
| } |
| } |
| } |
| |
| private function openArrayOfArrays(passedArray:Array , delimiter:String):String |
| { |
| if(passedArray ) |
| { |
| var tempArr:Array = new Array(); |
| var index:int = 0; |
| var count:int = passedArray.length; |
| while(index < count) |
| { |
| var currentArray:Array = passedArray[index] as Array; |
| if(currentArray) |
| tempArr.push(currentArray.join(delimiter)); |
| else |
| tempArr.push(passedArray[index]); |
| index++; |
| } |
| return tempArr.join(delimiter); |
| } |
| else |
| return ""; |
| } |
| |
| private function processNewWindowRequestToTool(event:Event = null, newResposeIdString:String = null, |
| sendDataEvenOnNoNewWindow:Boolean = false):void |
| { |
| if(recordRequestsQueue && recordRequestsQueue.length) |
| return; |
| |
| var responseIdString:String ; |
| var dataString:String; |
| var toBeSent:Boolean = false; |
| if(newResposeIdString != null) |
| responseIdString = newResposeIdString; |
| |
| if(queuedNewWindowRequestsToSendToTool && queuedNewWindowRequestsToSendToTool.length) |
| { |
| var appData:ApplicationDataToAgent = queuedNewWindowRequestsToSendToTool.shift() as ApplicationDataToAgent; |
| dataString = appData.currentResponseData; |
| if(!responseIdString) |
| responseIdString = appData.currentResponseIdString; |
| } |
| else if (sendDataEvenOnNoNewWindow) |
| dataString = ClientSocketHandler.noNewWindow; |
| |
| if(dataString && responseIdString) |
| sendData(responseIdString,dataString); |
| } |
| |
| private var queuedNewWindowRequestsToSendToTool:Array = new Array(); |
| |
| public function sendData(requestIdentifier:String,dataString:String=""):void |
| { |
| // TBD handle when we get if we were already in part processing we should |
| // queue this request |
| |
| if(!dataString) |
| dataString = ClientSocketHandler.nullValueIndicator; |
| |
| // here we assume that we got the request from the new data sending. |
| requestsSent.push(requestIdentifier); |
| |
| if(!currentDataFromAppToAgent) |
| currentDataFromAppToAgent = new ApplicationDataToAgent(currentApplicationId,requestIdentifier,dataString); |
| else |
| currentDataFromAppToAgent.init(currentApplicationId,requestIdentifier,dataString); |
| |
| |
| |
| if(currentDataFromAppToAgent.willDataBePendingAfterNextSend()) |
| isInPartDataProcessing = true; |
| |
| if(currentDataFromAppToAgent.sendNextSet(requestIdentifier) > 0) |
| isInPartDataProcessing = true; |
| // means current data could not be completely sent |
| else |
| isInPartDataProcessing = false; |
| |
| |
| |
| } |
| |
| |
| private function sendCurrentPartData( responseIdentifier:String):void |
| { |
| if(currentDataFromAppToAgent.isDataRemaining() == false) |
| { |
| |
| trace("ClientSocketHandler:sendCurrentPartData()-This should not have happened. Last time data is not there and we received a part request."); |
| // send a forceful completion |
| currentDataFromAppToAgent.sendForcefulCompletion(responseIdentifier); |
| |
| } |
| else |
| { |
| if(currentDataFromAppToAgent.willDataBePendingAfterNextSend()) |
| isInPartDataProcessing = true; |
| |
| if(currentDataFromAppToAgent.sendNextSet(responseIdentifier) > 0) |
| isInPartDataProcessing = true; |
| else |
| isInPartDataProcessing = false; |
| } |
| |
| |
| } |
| |
| |
| public static function sendDataWithoutFormatting(dataString:String):void |
| { |
| // if the required air libraries could not be loaded, |
| // we should not proceed communicating to QTP. |
| // without certian information using the library (e.g applicationTitle) |
| // qtp will hang. |
| if(!AutomationHelper.isAirClassLoaded()) |
| return; |
| |
| //trace ("sending " + dataString); |
| |
| |
| //str = str.concat(String(count)); |
| if(socket.connected) |
| { |
| socket.sendRequestString(dataString); |
| socket.flush(); |
| socket.readResponse(); |
| } |
| } |
| |
| public function processNewWindowInformation(windowId:String):void |
| { |
| ClientSocketHandler.isNewWindowRegistrationOver = false; |
| |
| if(isToolInRecordingStatus && (AutomationHelper.isAirClassLoaded()) ) |
| disableApplication(); |
| |
| |
| if(isToolInRunningStatus || isToolInRecordingStatus) |
| { |
| // if we are getting this in the middle of recording or replaying |
| // let us add to the queued request and once the |
| // recording or replaying is over let us handle it. |
| var newDataFromAppToAgent:ApplicationDataToAgent = new ApplicationDataToAgent(currentApplicationId,ClientSocketHandler.captureHandleForNewWindow,windowId); |
| queuedNewWindowRequestsToSendToTool.push(newDataFromAppToAgent); |
| } |
| else |
| sendData(ClientSocketHandler.captureHandleForNewWindow, windowId); |
| |
| } |
| |
| private static var _isNewWindowRegistrationOver:Boolean = false; |
| public static function get isNewWindowRegistrationOver():Boolean |
| { |
| return _isNewWindowRegistrationOver; |
| } |
| |
| public static function set isNewWindowRegistrationOver(inputData:Boolean):void |
| { |
| _isNewWindowRegistrationOver = inputData; |
| if(_isNewWindowRegistrationOver) |
| enableApplication(); |
| } |
| } |
| } |