HitManApplet is a Java applet that demonstrates how Javascript and Java
can interact on an HTML page using LiveConnect. HitManApplet uses getMember()
to search the JavaScript object hierarchy for VictimApplet objects; each
VictimApplet is then "hit." You should know HTML, Java, and Javascript
to easily understand what is happening in this example, but the sample
code will be described in detail below so you will probably be able to
follow along even if you are not an expert yet.
The Applets:
The Hitman:
A Victim:
Another Victim:
Notice that there are three rectangles on the page; Each of these is
an applet The top rectangle says "Hit Them!" and is an instance
of HitManApplet. The two lower rectangles with numbers inside them are
both instances of VictimApplet. Click the HitManApplet box and watch the
two other boxes increment together.
What these applets demonstrate is the use of the JSObject in Java to
find and access other Applets on a page. This particular functionality
could also be found in Java's AppletContext, but the technique which we
are demonstrating can be easily extended to provide functionality that
is not available from AppletContext. For instance, it could be used to
find the applets in a particular named frame. Or it could be slightly modified
to search for Plug-ins instead of Applets.
Here is the HTML source, so you can see how both applets are called
from HTML.
The Hitman:
<APPLET ARCHIVE="HitManApplet/HitManApplet.zip"
CODE="netscape/dts/examples/HitMan/HitManApplet.class"
WIDTH=100 HEIGHT=50 NAME=killer MAYSCRIPT>
</APPLET>
<BR>
A Victim:
<APPLET ARCHIVE="HitManApplet/HitManApplet.zip"
CODE="netscape/dts/examples/HitMan/VictimApplet.class"
WIDTH=70 HEIGHT=70 NAME=joe MAYSCRIPT>
</APPLET>
<BR>
Another Victim:
<APPLET ARCHIVE="HitManApplet/HitManApplet.zip"
CODE="netscape/dts/examples/HitMan/VictimApplet.class"
WIDTH=70 HEIGHT=70 NAME=joejr MAYSCRIPT>
</APPLET>
Notice that the APPLET tag is used to embed Java applets into HTML.
In this example there are three APPLET tags, so there are three instances
of our sample applets on the screen. The ARCHIVE attribute of the APPLET
tag specifies a single file containg all of the necessary classes for this
example. The applet class specified in the CODE attribute. Notice the class
in the first applet tag is HitManApplet.class and, for both the other applet
tags, the class is VictimApplet.class. The width and height of the rectangles
are designated by their corresponding attributes. Finally, each of the
applet tags end with MAYSCRIPT, which gives the applets permission to access
JavaScript functionality through the JSObject class.
The VictimApplet is very simple. (Look at the source
here.) The main feature of this class is the hit() method, which increments
the numHits instance variable. This method will get called by the HitManApplet.
Notice that this class does not use JSObject, but must still have MAYSCRIPT
set in the APPLET tag. This is because HitManApplet, which does use JSObject,
will be accessing VictimApplet. For security reasons, Netscape Navigator
will not allow a MAYSCRIPT'ed Applet to communicate with a non-MAYSCRIPT'ed
applet, and vice versa.
HitManApplet is much more interesting. (Look at the source
here.) Using the JSObject class, HitManApplet traverses the JavaScript
object structure to find all of the applets that reside in the same frame
as the HitManApplet. It then checks the type of each applet to determine
whether or not it is a member of the VictimApplet class. HitManApplet then
calls the hit() method of every VictimApplet.
Here is a detailed description of HitThem(), the HitManApplet method
which does all of the work.
JSObject window = JSObject.getWindow( this );
The getWindow static method takes an Applet, and returns a JSObject
that represents the window which contains the Applet. All JavaScript commands
must be performed in the context of a window, so this is always the first
call for an applet to make when working with JavaScript.
JSObject document = (JSObject) window.getMember("document");
JSObject applets = (JSObject) document.getMember("applets");
We must traverse the JavaScript object hierarchy to get to the JavaScript
"applets" object, which is an array of all applets in the given
window. The getMember method returns an Object. This Object must then be
cast up to the appropriate class. We know that the "document"
member of the window object will be of type JSObject, so we cast it as
such. We also know that the "applets" member of the document
object will be a JSObject as well. If our assumptions turn out to be incorrect,
Java will throw a ClassCastException. We will use this fact to our advantage
later. In any event, if all went well, we now have a JSObject which represents
an array of Applets on our page.
int numApplets = ((Double) applets.getMember("length")).intValue();
Since we know that the applets object is a JavaScript array, we also
know that the array will have a member called "length", which
has a numerical value. JavaScript returns all numerical values to Java
as type java.lang.Double, so we cast the return value of applets.getMember("length")
as such. However, what we need is an integer value. We get this from Double's
intValue() method.
targetLoop: for( int index = 0; index < numApplets; index++ ) {
Now that we have a bounding value, we can iterate through the list of
applets. We label this loop targetLoop. You will see why shortly.
Object theApplet = applets.getSlot( index );
For JavaScript arrays, we can call the getSlot method to get indexed
members of the array. We don't cast the object yet, since we don't know
exactly what class it belongs to.
try {
targetApplet = (VictimApplet) theApplet;
}
catch( ClassCastException e ) {
continue targetLoop;
}
Now we can make use of the ClassCastException, as alluded to above.
We try casting the theApplet object into a VictimApplet. If theApplet is
not a member of the VictimApplet class, or a subclass thereof, then Java
will throw a ClassCastException. In that event, we catch the exception
and continue on to the next iteration of targetLoop. (We could have left
out the targetLoop label, but that would have made the code somewhat less
readable.)
targetApplet.hit();
Finally, if no exception was thrown, then we know that targetApplet
is a proper victim. We call that Applet's hit() method, and continue with
the next Applet. When all of the Applets have been tried, we are done.
- Related Reading:
Any sample code included above is provided for your use on an "AS IS" basis, under the Netscape License Agreement - Terms of Use