Sunday, September 20, 2009

Using Java Robot to type text strings

The Java Robot class is very useful for automating various tasks that normally require user interaction. However, it lacks a rather simple but useful feature - it cannot type a string of text, just a single key code. I had to implement this when I worked on one of my projects and to my surprise an extensive googling session showed that quite a lot of people are looking for such functionality.

The SmartRobot class below extends the standard Java Robot class adding to "type(String text)" and a few other useful methods:
import java.awt.AWTException;
import java.awt.Robot;
import java.awt.event.KeyEvent;

public class SmartRobot extends Robot {

public SmartRobot() throws AWTException {
super();
}

public void keyType(int keyCode) {
keyPress(keyCode);
delay(50);
keyRelease(keyCode);
}

public void keyType(int keyCode, int keyCodeModifier) {
keyPress(keyCodeModifier);
keyPress(keyCode);
delay(50);
keyRelease(keyCode);
keyRelease(keyCodeModifier);
}


public void type(String text) {
String textUpper = text.toUpperCase();

for (int i=0; i<text.length(); ++i) {
typeChar(textUpper.charAt(i));
}
}

private void typeChar(char c) {
boolean shift = true;
int keyCode;

switch (c) {
case '~':
keyCode = (int)'`';
break;
case '!':
keyCode = (int)'1';
break;
case '@':
keyCode = (int)'2';
break;
case '#':
keyCode = (int)'3';
break;
case '$':
keyCode = (int)'4';
break;
case '%':
keyCode = (int)'5';
break;
case '^':
keyCode = (int)'6';
break;
case '&':
keyCode = (int)'7';
break;
case '*':
keyCode = (int)'8';
break;
case '(':
keyCode = (int)'9';
break;
case ')':
keyCode = (int)'0';
break;
case ':':
keyCode = (int)';';
break;
case '_':
keyCode = (int)'-';
break;
case '+':
keyCode = (int)'=';
break;
case '|':
keyCode = (int)'\\';
break;
// case '"':

// keyCode = (int)'\'';

// break;

case '?':
keyCode = (int)'/';
break;
case '{':
keyCode = (int)'[';
break;
case '}':
keyCode = (int)']';
break;
case '<':
keyCode = (int)',';
break;
case '>':
keyCode = (int)'.';
break;
default:
keyCode = (int)c;
shift = false;
}
if (shift)
keyType(keyCode, KeyEvent.VK_SHIFT);
else
keyType(keyCode);
}

private int charToKeyCode(char c) {
switch (c) {
case ':':
return ';';
}
return (int)c;
}
}


The code can be downloaded here

Labels: , , , , , ,

Tuesday, October 16, 2007

Transferring information between Java applets

I stumbled upon a rather lengthy article at TechRepublic about a workaround for one of the Java applet security limitations, which does not allow any information to be passed between Java applets originating from different servers. The article talks about transferring files, but there is no reason not to generalize it to the transfer of any kind of information.

Their solution is to write what they call a "middleman" - an application that should reside on a web server and route the traffic between its applet and the "middleman" application running on the server of the other applet, which in its turn should forward the information to the receiving applet.

Well... it's surely an interesting exercise, but... guys, this is stupid!

The following trivial hack using Javascript allows you to do the same, i.e. pass information between two Java applets originating from different servers, in a fraction of an effort needed to implement the hack from TechRepublic article. This is actually very simple - the above Java applets are not allowed to communicate with each other, but they both can communicate with the Javascript!

There are a couple of ways to call Java code from Javascript, but the simplest is "java.package.class.staticMethod()". So all you have to do is to call the relevant methods of both classes from Javascript and pass the information from one to another.

Links:
Java applet security limitations, Sun Java security specifications

Labels: , ,