/*
* Copyright 2014, Synthuse.org
* Released under the Apache Version 2.0 License.
*
* last modified by ejakubowski
*/
package org.synthuse.commands;
import java.awt.Point;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.sql.Timestamp;
import java.util.Date;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import org.synthuse.*;
import com.sun.jna.platform.win32.WinDef.HWND;
public class BaseCommand {
static String WIN_XML = "";
static long LAST_UPDATED_XML = 0;
protected Api api = new Api();
protected UiaBridge uiabridge = new UiaBridge();
protected CommandProcessor parentProcessor = null;
protected int getExecuteErrorCount() {
return parentProcessor.executeErrorCount;
}
protected void setExecuteErrorCount(int val) {
parentProcessor.executeErrorCount = val;
}
protected String getCurrentCommand() {
return parentProcessor.currentCommandText;
}
protected void setCurrentCommand(String val) {
parentProcessor.currentCommandText = val;
}
protected boolean isProcessorStopped() {
return CommandProcessor.STOP_PROCESSOR.get();
}
public BaseCommand(CommandProcessor cp) { // should pass in the parent command processor
parentProcessor = cp;
}
public void appendError(Exception e) {
setExecuteErrorCount(getExecuteErrorCount() + 1);
StringWriter sw = new StringWriter();
e.printStackTrace(new PrintWriter(sw));
parentProcessor.lastError += new Timestamp((new Date()).getTime()) + " - " + sw.toString() + "\n";
try {
sw.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
public void appendError(String msg) {
setExecuteErrorCount(getExecuteErrorCount() + 1);
parentProcessor.lastError += new Timestamp((new Date()).getTime()) + " - " + msg + "\n";
}
public boolean checkArgumentLength(String[] args, int expectedLength) {
if (args.length < expectedLength) {
appendError("Error: expected at least " + expectedLength + " arguments (" + getCurrentCommand() + "[" + args.length + "])");
return false;
}
return true;
}
public boolean checkFirstArgumentLength(String[] args) {
if (args[0].length() <= 0) {
appendError("Error: command '" + getCurrentCommand() + "' failed, expected first argument length > 0");
return false;
}
return true;
}
public boolean checkIsNumeric(String val) {
try {
Long.parseLong(val);
} catch(NumberFormatException e) {
appendError("Error: command '" + getCurrentCommand() + "' failed, was expecting a numeric value instead '" + val + "'");
return false;
}
return true;
}
public boolean whenFalseAppendError(boolean cmdResult) {
if (!cmdResult)
appendError("Error: command '" + getCurrentCommand() + "' failed");
return cmdResult;
}
public void forceXmlRefresh() {
WIN_XML = WindowsEnumeratedXml.getXml();
LAST_UPDATED_XML = System.nanoTime();
}
public void forceWin32OnlyXmlRefresh() {
WIN_XML = WindowsEnumeratedXml.getWin32Xml();
LAST_UPDATED_XML = System.nanoTime();
}
public void onlyRefreshWin32(boolean flg) {
SynthuseDlg.config.disableUiaBridge = flg + "";
}
public void targetXmlRefresh(String xpath) {
if (WIN_XML.isEmpty()) //can't target refresh unless there is XML to start with
{
forceXmlRefresh();
return;
}
//WIN_XML = WindowsEnumeratedXml.getXml();
LAST_UPDATED_XML = System.nanoTime();
String resultStr = "";
String resultHwndStr = "";
List<String> resultList = WindowsEnumeratedXml.evaluateXpathGetValues(WIN_XML, xpath);
for(String item: resultList) {
//System.out.println("xpath result item: " + item);
resultStr = item;
if (item.contains("hwnd=")) {
List<String> hwndList = WindowsEnumeratedXml.evaluateXpathGetValues(item, "//@hwnd");
if (hwndList.size() > 0)
resultHwndStr = hwndList.get(0).replaceAll("[^\\d-.]", ""); //get first hwnd;
}
else
resultStr = item;
break;
}
String newXml = "";
Map<String, WindowInfo> infoList;
if (resultHwndStr.contains("-")) { //uiabridge target refresh
resultHwndStr = resultHwndStr.split("-")[1];
infoList = WindowsEnumeratedXml.EnumerateWindowsWithUiaBridge(uiabridge, resultHwndStr, "*");
newXml = WindowsEnumeratedXml.generateWindowsXml(infoList, "updates");
//System.out.println("newXml: " + newXml);
}
else
{ // native target refresh
infoList = new LinkedHashMap<String, WindowInfo>();
HWND parentHwnd = Api.GetHandleFromString(resultHwndStr);
WindowInfo wi = new WindowInfo(parentHwnd, false);
infoList.put(wi.hwndStr, wi);
infoList.putAll(WindowsEnumeratedXml.EnumerateWin32ChildWindows(parentHwnd));
//WindowsEnumeratedXml.appendUiaBridgeWindows(infoList); //if we need this we should specify a runtimeID handle instead
newXml = WindowsEnumeratedXml.generateWindowsXml(infoList, "updates");
System.out.println("newNativeXml: " + newXml);
}
int pos = WIN_XML.indexOf(resultStr);
WIN_XML = WIN_XML.substring(0, pos) + newXml + WIN_XML.substring(pos + resultStr.length());
}
public String getWindowTypeWithXpath(String xpath) {
String result = "";
double secondsFromLastUpdate = ((double)(System.nanoTime() - LAST_UPDATED_XML) / 1000000000);
if (secondsFromLastUpdate > CommandProcessor.XML_UPDATE_THRESHOLD) { //default 5 second threshold
WIN_XML = WindowsEnumeratedXml.getXml();
LAST_UPDATED_XML = System.nanoTime();
}
String resultStr = "";
List<String> resultList = WindowsEnumeratedXml.evaluateXpathGetValues(WIN_XML, xpath);
if (resultList.size() > 0)
{
resultStr = resultList.get(0).trim();
if (resultStr.startsWith("<winfrm "))
result = "winfrm";
else if(resultStr.startsWith("<win "))
result = "win";
else if(resultStr.startsWith("<wpf "))
result = "wpf";
else if(resultStr.startsWith("<silver "))
result = "silver";
else if(resultStr.startsWith("<menu "))
result = "menu";
else
result = "other";
}
return result;
}
public WinPtr findHandleWithXpath(String xpath) {
return findHandleWithXpath(xpath, false);
}
public WinPtr findHandleWithXpath(String xpath, boolean ignoreFailedFind) {
WinPtr result = new WinPtr();
double secondsFromLastUpdate = ((double)(System.nanoTime() - LAST_UPDATED_XML) / 1000000000);
if (secondsFromLastUpdate > CommandProcessor.XML_UPDATE_THRESHOLD) { //default 5 second threshold
WIN_XML = WindowsEnumeratedXml.getXml();
LAST_UPDATED_XML = System.nanoTime();
}
//WindowsEnumeratedXml.evaluateXpathGetValues(WIN_XML, xpath);
String resultStr = "";
List<String> resultList = WindowsEnumeratedXml.evaluateXpathGetValues(WIN_XML, xpath);
for(String item: resultList) {
//System.out.println("xpath result item: " + item);
if (item.contains("hwnd=")) {
List<String> hwndList = WindowsEnumeratedXml.evaluateXpathGetValues(item, "//@hwnd");
if (hwndList.size() > 0)
resultStr = hwndList.get(0); //get first hwnd;
}
else
resultStr = item;
if (item.contains("hmenu=")) { //get menu information, useful for getting center of menu
List<String> hmenuList = WindowsEnumeratedXml.evaluateXpathGetValues(item, "//@hmenu");
if (hmenuList.size() > 0)
result.hmenuStr = hmenuList.get(0).replaceAll("[^\\d-.]", ""); //get first hmenu;
if (item.contains("id=")) {
List<String> menuidList = WindowsEnumeratedXml.evaluateXpathGetValues(item, "//@position");
if (menuidList.size() > 0)
result.hmenuPos = Integer.parseInt(menuidList.get(0).replaceAll("[^\\d-.]", "")); //get first id;
}
}
break;// we only care about the first item
}
resultStr = resultStr.replaceAll("[^\\d-.]", ""); //remove all non-numeric values (except dash -)
if (WinPtr.isWpfRuntimeIdFormat(resultStr)) {
result.runtimeId = resultStr;
if (!ignoreFailedFind && result.isEmpty())
appendError("Error: Failed to find window handle matching: " + xpath);
}
else {
result.hWnd = Api.GetHandleFromString(resultStr);
if (!ignoreFailedFind && !api.user32.IsWindow(result.hWnd))
appendError("Error: Failed to locate window HWND(" + resultStr + ") from : " + xpath);
}
return result;
}
public int findMenuIdWithXpath(String xpath) {
int result = 0;
double secondsFromLastUpdate = ((double)(System.nanoTime() - LAST_UPDATED_XML) / 1000000000);
if (secondsFromLastUpdate > CommandProcessor.XML_UPDATE_THRESHOLD) { //default 5 second threshold
WIN_XML = WindowsEnumeratedXml.getXml();
LAST_UPDATED_XML = System.nanoTime();
}
//WindowsEnumeratedXml.evaluateXpathGetValues(WIN_XML, xpath);
String resultStr = "";
List<String> resultList = WindowsEnumeratedXml.evaluateXpathGetValues(WIN_XML, xpath);
for(String item: resultList) {
if (item.contains("hmenu=")) {
List<String> list = WindowsEnumeratedXml.evaluateXpathGetValues(item, "//@id");
if (list.size() > 0)
resultStr = list.get(0); //get first id
}
else
resultStr = item;
break;
}
resultStr = resultStr.replaceAll("[^\\d.]", ""); //remove all non-numeric values
//System.out.println("findMenuIdWithXpath: " + resultStr);
if (resultStr.isEmpty())
appendError("Error: Failed to find window handle matching: " + xpath);
else
result = Integer.parseInt(resultStr);
return result;
}
public Point getCenterWindowPosition(WinPtr handle) {
Point p = null;
if (handle.isWin32())
p = api.getWindowPosition(handle.hWnd);
else
p = uiabridge.getCenterOfElement(handle.runtimeId);
return p;
}
public Point getCenterWindowPosition(WinPtr handle, String windowType) {
Point p = null;
if (handle.isWpf() || windowType.equals("winfrm") || windowType.equals("wpf") || windowType.equals("silver"))
p = uiabridge.getCenterOfElement(handle.runtimeId);
else if (windowType.equals("win"))
p = api.getWindowPosition(handle.hWnd);
else if (windowType.equals("menu"))
p = api.getMenuItemPosition(handle.hWnd, MenuInfo.GetHandleMenuFromString(handle.hmenuStr), handle.hmenuPos);
return p;
}
public String convertListToString(List<String> listStr, String delimiter) {
StringBuilder result = new StringBuilder("");
for (String item: listStr) {
result.append(item + delimiter);
}
return result.toString();
}
public void killStatusWindow() {
parentProcessor.currentStatusWin.dispose();
parentProcessor.currentStatusWin = null;
}
}