Applets
Where Do Applets and Classes Come from?
When
a web browser sees an applet tag and
decides to download and play the applet,
it
starts a long chain of events. Let's say your browser sees the following applet tag:
<APPLET codebase="http://metalab.unc.edu/javafaq/classes"
code="Animation.class"
width="200" height="100" >
<PARAM NAME = “FRAMErATE” VALUE
= “10”>
</APPLET>
1.
The web browser sets aside a rectangular area on the
page 200 pixels wide and
100 pixels high. In most web browsers, this area has a
fixed size and cannot be
modified once created. The appletviewer in the JDK
is a notable exception.
2.
The browser opens a connection to the server specified
in the codebase parameter, using port 80
unless another port is specified in the codebase
URL. If there's no codebase parameter,
then the browser connects to the same server that served the HTML page.
3.
The browser requests the .class file from the
web server as it requests any other file. If a codebase
is present, it is prefixed to the requested filename. Otherwise, the
document base (the directory that contains the HTML page) is used. For example:
GET
/javafaq/classes/Animation.class HTTP 1.0
4.
The server responds by sending a MIME header followed
by a blank line (\r\n) followed by the
binary data in the .class file. A properly configured server sends .class
files with MIME type application/octet-stream.
For example:
HTTP 1.0 200 OK
Date: Mon, 10 Jun 1999
17:11:43 GMT
Server: Apache/1.2.8
Content-type:
application/octet-stream
Content-length: 2782
Last-modified: Fri, 08 Sep
1998 21:53:55 GMT
5.
The web browser receives the data and stores it in a
byte array. The byte code verifier goes over the byte codes that have been
received to make sure they don't do anything forbidden, such as converting an
integer into a pointer.
6.
If the byte code verifier is satisfied with the bytes
that were downloaded, then the raw data is converted into a Java class using
the defineClass( ) and loadClass( ) methods of the current ClassLoader object.
7.
The web browser instantiates the Animation class using its noargs constructor.
8.
The web browser invokes the init( ) method of Animation.
9. The
web browser invokes the start( ) method
of Animation.
10. If
the Animation class references another
class, the Java interpreter first searches for
the new class in the user's CLASSPATH.
If the class is found in the user's CLASSPATH,
then it is created from the .class file on the
user's hard drive. Otherwise the web
browser goes back to the site from which this class came
and downloads the .class file for the new class. The same procedure is
followed for the new class and any other
class that is downloaded from the Net. If the new class
cannot be found, a
ClassNotFoundException is
thrown
Who Can an Applet Talk to and What Can It Say?
1.
Applets cannot access arbitrary addresses in memory.
Unlike the other restrictions in the list, which are enforced by the browser's SecurityManager instance, this restriction is a
property of the Java language itself and the byte code verifier.
2.
Applets cannot access the local filesystem in any way.
They cannot read from or write to the local filesystem nor can they find out
any information about files. Therefore, they cannot find out whether a file
exists or what its modification date may be.
3.
Applets cannot launch other programs on the client. In
other words, they
cannot call System.exec( ) or
Runtime.exec( ).
4.
Applets cannot load native libraries or define native
method calls.
5.
Applets are not allowed to use System.getProperty( ) in a way that reveals
information about the user or the user's machine, such as
a username or home
directory. They may use System.getProperty(
) to find out what version of
Java is in use.
6. Applets
may not define any system properties.
7.
In Java 1.1 and later, applets may not create or
manipulate any Thread or
ThreadGroup that is
not in the applet's own ThreadGroup. They
may do this
in Java 1.0.
8. Applets
cannot define or use a new instance of ClassLoader,
SecurityManager, ContentHandlerFactory, SocketImplFactory,
or URLStreamHandlerFactory. They must use
the ones already in place.
9.
An applet can only open network connections to the host
from which the applet itself was downloaded.
10. An
applet cannot listen on ports below 1,024. (Internet Explorer 5.0 doesn't
allow applets to listen on any ports.)
11. Even
if an applet can listen on a port, it can accept incoming connections only
from the host from which the applet itself was downloaded.
The Network Methods of java.applet.Applet
Using
java.applet.Applet to Download Data
public
URL getDocumentBase( )
The
getDocumentBase( ) method returns the URL of the page containing the applet.
Example
import
java.applet.*;
import
java.awt.*;
public
class WhereAmI extends Applet {
public void paint (Graphics g) {
g.drawString(this.getDocumentBase().toString( ), 25,
50);
}
}
public
URL getCodeBase( )
The
getCodeBase( ) method returns the URL of the directory where the applet is
located.
If the applet is in a JAR archive, then the codebase is the URL of the directory
where the JAR archive is. If the applet is in a package (e.g.com.macfaq.applets.MyApplet
instead of just MyApplet), then the codebase is the directory or JAR archive
containing the outermost package such as com.
Downloading
Images
public Image getImage(URL url)
Image
myLogo = getImage (new URL("http://metalab.unc.edu/java/cup.gif"));
public Image getImage(URL url, String name)
Image
logo = this.getImage(new URL("http://metalab.unc.edu/java/"),
"cup.gif");
Example
public
class ImageView extends Applet {
Image
picture;
public
void init( ) {
try {
URL u
= new URL(this.getCodeBase( ), this.getParameter("IMAGE"));
this.picture
= this.getImage(u);
System.err.println(u);
}
catch
(MalformedURLException e) {
//
shouldn't happen, the codebase is never malformed
}
}
public
void paint (Graphics g) {
g.drawImage(this.picture, 0, 0, this);
}
}
Note:
The
getImage( ) method returns immediately, even before it knows whether the
image
actually exists. The image isn't loaded until some other part of the program
actually
tries to draw it, or you explicitly force the image to start loading
Downloading
Sounds
public
void play(URL u)
The
play( ) method looks for a sound file at the URL u. If the sound file is found,
then it is downloaded and played. Otherwise, nothing happens.
Example
try {
URL
soundLocation =
new
URL( "http://metalab.unc.edu/java/course/week9/spacemusic.au" );
play(soundLocation);
}
catch
(MalformedURLException e) {
System.err.println(
Example
import
java.applet.*;
import
java.awt.*;
import
java.net.*;
public
class PlaySound extends Applet {
public
void init( ) {
try {
URL u = new URL(this.getCodeBase( ), this.getParameter("sound"));
this.play(u);
}
catch
(MalformedURLException e) {}
}
}
public
void play(URL url, String filename)
This
is similar to the previous method, except that it uses the url argument to find
the sound file's directory and the filename argument to get the actual
filename. For
Example:
play(new
URL("http://www.macfaq.com/", "gong.au"));
public
AudioClip getAudioClip(URL u)
The
java.applet.AudioClip interface represents a sound. You can download a sound
from a web site with the getAudioClip( ) method. Once you have an AudioClip
object, play it at your leisure by calling the clip's play( ) and loop( ) methods;
play( ) plays the file once, and loop( ) plays it repeatedly. Both of these methods
let you keep the audio clip around for future use—unlike the play( ) method of
the last section, which discarded the audio data after it had finished.
Example
AudioClip
theGong;
try {
URL u
= new URL(http://metalab.unc.edu/javafaq/gong.au);
theGong
= this.getAudioClip(u);
theGong.loop();
//theGong.play();
}
catch
(MalformedURLException e) {
System.err.println(e);
}
public
AudioClip getAudioClip(URL url, String filename)
Example
import java.applet.*;
import java.awt.*;
public class RelativeBeep
extends Applet implements Runnable {
private AudioClip beep;
private boolean stopped =
false;
public void init( ) {
beep =
this.getAudioClip(this.getDocumentBase( ),"sounds/beep.au");
if (beep != null) {
Thread t = new Thread(this);
t.start( );
}
}
public void start( ) {
this.stopped
= false;
}
public void stop( ) {
this.stopped
= true;
}
public void run( ) {
Thread.currentThread(
).setPriority(Thread.MIN_PRIORITY);
while
(true) {
if
(!stopped) beep.play( );
try
{
Thread.sleep(5000);
}
catch (InterruptedException
e) {}
The MediaTracker Class
1. This class is used for
loading multiple images.
2. The
java.awt.MediaTracker class
can track the loading status of many different images and organize them into
logical groups.
3. Create
an instance of MediaTracker
and then use the MediaTracker's
addImage(Image pic,
int ID ) method for each Image.
4.
ID does not have to be unique; it is really a group ID
that is used to organize different images into groups.
5.
Before using the image, call a method such as checkID( ) to see
whether the image is ready.
6. Other
methods let you force loading to start, discover which images in a group have
failed to load successfully, wait for images to finish loading, and so on.
7.
The Constructor
The MediaTracker class has one constructor:
public MediaTracker(Component comp)
This constructor creates a MediaTracker object that tracks
images for a specified Component. It's usually invoked like this:
MediaTracker tracker = new MediaTracker(this);
8.
Adding Images to MediaTrackers
Image
picture = this.getImage(this.getDocumentBase( ), "logo.gif");
MediaTracker
tracker = new MediaTracker(this);
tracker.addImage(picture,
1);
public
void addImage(Image image, int id, int width, int height)
The
image will eventually be displayed scaled to the width ‘width’ and the height ‘height’.
9.
Checking Whether Media Has Loaded
There
are four check methods that tell you whether particular images tracked by a
MediaTracker
have loaded. These are:
public
boolean checkID(int id)
public
boolean checkID(int id, boolean load)
public
boolean checkAll( )
public
boolean checkAll(boolean load)
10. public
boolean checkID(int id)
This
method checks whether all the images with the indicated ID that are tracked by
this
MediaTracker have finished loading. If they have, it returns true; otherwise,
it
returns
false. Multiple Image objects may have the same ID.
public
void paint(Graphics g) {
if
(theTracker.checkID(1)) {
g.drawImage(thePicture,
0, 0, this);
}
else
{
g.drawString("Loading
Picture. Please hang on", 25, 50);
}
}
11. public
boolean checkID(int id, boolean load)
This
method checks whether all the Image objects with the indicated ID that are tracked
by this MediaTracker have finished loading. If they have, it returns true; otherwise,
it returns false. Multiple Image objects may have the same ID. If the boolean
argument load is true, all images with that ID that are not yet being loaded will
begin loading.
public
void paint(Graphics g) {
if
(theTracker.checkID(1, true)) {
g.drawImage(thePicture,
0, 0, this);
}
else
{
g.drawString("Loading
Picture. Please hang on", 25, 50);
}
}
12. public
boolean checkAll( )
This
method checks whether all the Image objects that are tracked by this object
have
finished
loading. ID numbers are not considered. If all images are loaded, it returns
true;
otherwise, it returns false. It does not start loading images that are not
already
loading.
13. public
boolean checkAll(boolean load)
This
version of checkAll( ) checks whether all the Image objects that are tracked by
this
MediaTracker have finished loading. If they have, it returns true; otherwise,
it
returns
false. If the boolean argument load is true, then it also starts loading any
Image
objects that are not already being loaded.
14. public
void waitForID(int id) throws InterruptedException
This
method forces the images with the ID number id that are tracked by this
MediaTracker
to start loading and then waits until each one has either finished
loading,
aborted, or received an error.
try {
tracker.waitForID(1);
}
catch
(InterruptedException e) {
}
15. public
boolean waitForAll( ) throws InterruptedException
The
waitForAll( ) method starts loading all the images that are tracked by this
MediaTracker
in up to four separate threads while pausing the thread that invoked it
until
each tracked image has either finished loading, aborted, or received an error.
An
InterruptedException
is thrown if another thread interrupts the waiting thread.
Downloading the images is easy
à
Create URL objects that point to each image.
à
Then call Applet’s ‘Image getImage( )’ with each
URL.
à
Add returned image to MediaTracker Object.
à
Use it (MediaTracker) to force the images to
load;
à
Then use waitForAll( ) to make sure all frames
have loaded.
à
Finally, call drawImage( ) method of class
Graphics
to display the images in sequence.
Example
A Very Simple Animator Applet
public
class Animator extends Applet
implements
Runnable, MouseListener {
private
boolean running = false;
private
int currentCell = 0;
private
Vector cells = new Vector( );
private
MediaTracker tracker;
public
void init( ) {
this.addMouseListener(this);
String nextCell;
this.tracker = new MediaTracker(this);
for
(int i = 0; (nextCell = this.getParameter("Cell" + i)) != null; i++)
{
Image img = this.getImage(this.getDocumentBase( ),
nextCell);
cells.addElement(img);
tracker.addImage(img, i);
//
start loading the image in a separate thread
tracker.checkID(i, true);
}
}
public
void run( ) {
//
wait for all images to finish loading
try {
this.tracker.waitForAll(
);
}
catch
(InterruptedException e) {
}
for
(currentCell=0; currentCell < cells.size( ); currentCell++)
{
if (!running) return;
// paint the cell
this.repaint( );
//
sleep for a tenth of a second
//
i.e. play ten frames a second
try {
Thread.sleep(100);
}
catch
(InterruptedException ie) {}
}
}
public
void stop( ) {
this.running = false;
}
public
void start( ) {
this.running = true;
Thread play = new Thread(this);
play.start( );
}
public
void paint(Graphics g) {
g.drawImage((Image) cells.elementAt(currentCell), 0, 0,
this);
}
//
The convention is that a mouseClick starts
// a stopped
applet and stops a running applet.
public
void mouseClicked(MouseEvent e) {
if (running) {
this.stop( );
}
else {
this.start( );
}
}
//
do-nothing methods required to implement the MouseListener
interface
public
void mousePressed(MouseEvent e) {}
public
void mouseReleased(MouseEvent e) {}
public
void mouseEntered(MouseEvent e) {}
public
void mouseExited(MouseEvent e) {}
}