This commit is contained in:
Andrei Dmitriev 2008-04-04 20:32:59 +04:00
commit 31835022c4
8 changed files with 731 additions and 9 deletions
jdk
src
share/classes/java/awt
solaris/native/sun
test/java/awt
Window/PropertyChangeListenerLockSerialization
appletviewer/IOExceptionIfEncodedURLTest

@ -634,7 +634,9 @@ public abstract class Component implements ImageObserver, MenuContainer,
*/
private PropertyChangeSupport changeSupport;
private transient final Object changeSupportLock = new Object();
// Note: this field is considered final, though readObject() prohibits
// initializing final fields.
private transient Object changeSupportLock = new Object();
private Object getChangeSupportLock() {
return changeSupportLock;
}
@ -1003,7 +1005,7 @@ public abstract class Component implements ImageObserver, MenuContainer,
/**
* Gets this component's locking object (the object that owns the thread
* sychronization monitor) for AWT component-tree and layout
* synchronization monitor) for AWT component-tree and layout
* operations.
* @return this component's locking object
*/
@ -8310,6 +8312,8 @@ public abstract class Component implements ImageObserver, MenuContainer,
private void readObject(ObjectInputStream s)
throws ClassNotFoundException, IOException
{
changeSupportLock = new Object();
s.defaultReadObject();
appContext = AppContext.getAppContext();

@ -54,7 +54,7 @@ Java_sun_awt_DefaultMouseInfoPeer_fillPointWithCoords(JNIEnv *env, jclass cls,
int i;
int32_t xr, yr, xw, yw;
uint32_t keys;
BOOL pointerFound;
Bool pointerFound;
AWT_LOCK();
if (pointClass == NULL) {
@ -102,7 +102,7 @@ JNIEXPORT jboolean JNICALL Java_sun_awt_DefaultMouseInfoPeer_isWindowUnderMouse
int32_t xr = 0, yr = 0, xw = 0, yw = 0;
uint32_t keys = 0;
uint32_t nchildren = 0;
BOOL pointerFound = 0;
Bool pointerFound = 0;
struct FrameData *wdata = NULL;
jobject winPeer = NULL;

@ -1234,7 +1234,7 @@ Java_sun_awt_X11_XWindow_initIDs
}
}
JNIEXPORT int JNICALL
JNIEXPORT jint JNICALL
Java_sun_awt_X11_XWindow_getKeySymForAWTKeyCode(JNIEnv* env, jclass clazz, jint keycode) {
return awt_getX11KeySym(keycode);
}

@ -359,7 +359,7 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XDestroyWindow
XDestroyWindow( (Display *)jlong_to_ptr(display),(Window) window);
}
JNIEXPORT int JNICALL Java_sun_awt_X11_XlibWrapper_XGrabPointer
JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XGrabPointer
(JNIEnv *env, jclass clazz, jlong display, jlong window,
jint owner_events, jint event_mask, jint pointer_mode,
jint keyboard_mode, jlong confine_to, jlong cursor, jlong time)
@ -377,7 +377,7 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XUngrabPointer
XUngrabPointer( (Display *)jlong_to_ptr(display), (Time) time);
}
JNIEXPORT int JNICALL Java_sun_awt_X11_XlibWrapper_XGrabKeyboard
JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XGrabKeyboard
(JNIEnv *env, jclass clazz, jlong display, jlong window,
jint owner_events, jint pointer_mode,
jint keyboard_mode, jlong time)
@ -621,7 +621,7 @@ JNIEXPORT void JNICALL Java_sun_awt_X11_XlibWrapper_XSync
}
JNIEXPORT int JNICALL Java_sun_awt_X11_XlibWrapper_XTranslateCoordinates
JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XTranslateCoordinates
(JNIEnv *env, jclass clazz, jlong display, jlong src_w, jlong dest_w,
jlong src_x, jlong src_y, jlong dest_x_return, jlong dest_y_return,
jlong child_return)
@ -634,7 +634,7 @@ JNIEXPORT int JNICALL Java_sun_awt_X11_XlibWrapper_XTranslateCoordinates
(Window *) jlong_to_ptr(child_return));
}
JNIEXPORT int JNICALL Java_sun_awt_X11_XlibWrapper_XEventsQueued
JNIEXPORT jint JNICALL Java_sun_awt_X11_XlibWrapper_XEventsQueued
(JNIEnv *env, jclass clazz, jlong display, jint mode) {
AWT_CHECK_HAVE_LOCK();

@ -0,0 +1,402 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
@test
@bug 6681889
@summary Showing a deserialized frame should not throw NPE
@author anthony.petrov@...: area=awt.toplevel
@run main PropertyChangeListenerLockSerialization
*/
/**
* PropertyChangeListenerLockSerialization.java
*
* summary: Showing a deserialized frame should not throw NPE
*/
import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
public class PropertyChangeListenerLockSerialization
{
private static void init()
{
//*** Create instructions for the user here ***
String[] instructions =
{
"This is an AUTOMATIC test, simply wait until it is done.",
"The result (passed or failed) will be shown in the",
"message window below."
};
Sysout.createDialog( );
Sysout.printInstructions( instructions );
File file =
new File(System.getProperty("test.classes", "."), "frame.ser");
Frame f = new Frame("Frame");
f.setBounds(250, 50, 300, 300);
try {
OutputStream o = new FileOutputStream(file);
ObjectOutputStream oo = new ObjectOutputStream(o);
oo.writeObject(f);
oo.close();
} catch (IOException ex) {
ex.printStackTrace();
fail("Unable to serialize the frame: " + ex);
}
// Cleanup the frame
f.dispose();
f = null;
try {
ObjectInputStream i = new ObjectInputStream(new FileInputStream(file));
f = (Frame)i.readObject();
f.show();
} catch (NullPointerException ex) {
ex.printStackTrace();
fail("The NullPointerException has been thrown: " + ex);
} catch (Exception ex) {
ex.printStackTrace();
fail("Error while deserializing the frame: " + ex);
}
// Cleanup the frame
f.dispose();
f = null;
pass();
}//End init()
/*****************************************************
* Standard Test Machinery Section
* DO NOT modify anything in this section -- it's a
* standard chunk of code which has all of the
* synchronisation necessary for the test harness.
* By keeping it the same in all tests, it is easier
* to read and understand someone else's test, as
* well as insuring that all tests behave correctly
* with the test harness.
* There is a section following this for test-
* classes
******************************************************/
private static boolean theTestPassed = false;
private static boolean testGeneratedInterrupt = false;
private static String failureMessage = "";
private static Thread mainThread = null;
private static int sleepTime = 300000;
// Not sure about what happens if multiple of this test are
// instantiated in the same VM. Being static (and using
// static vars), it aint gonna work. Not worrying about
// it for now.
public static void main( String args[] ) throws InterruptedException
{
mainThread = Thread.currentThread();
try
{
init();
}
catch( TestPassedException e )
{
//The test passed, so just return from main and harness will
// interepret this return as a pass
return;
}
//At this point, neither test pass nor test fail has been
// called -- either would have thrown an exception and ended the
// test, so we know we have multiple threads.
//Test involves other threads, so sleep and wait for them to
// called pass() or fail()
try
{
Thread.sleep( sleepTime );
//Timed out, so fail the test
throw new RuntimeException( "Timed out after " + sleepTime/1000 + " seconds" );
}
catch (InterruptedException e)
{
//The test harness may have interrupted the test. If so, rethrow the exception
// so that the harness gets it and deals with it.
if( ! testGeneratedInterrupt ) throw e;
//reset flag in case hit this code more than once for some reason (just safety)
testGeneratedInterrupt = false;
if ( theTestPassed == false )
{
throw new RuntimeException( failureMessage );
}
}
}//main
public static synchronized void setTimeoutTo( int seconds )
{
sleepTime = seconds * 1000;
}
public static synchronized void pass()
{
Sysout.println( "The test passed." );
Sysout.println( "The test is over, hit Ctl-C to stop Java VM" );
//first check if this is executing in main thread
if ( mainThread == Thread.currentThread() )
{
//Still in the main thread, so set the flag just for kicks,
// and throw a test passed exception which will be caught
// and end the test.
theTestPassed = true;
throw new TestPassedException();
}
theTestPassed = true;
testGeneratedInterrupt = true;
mainThread.interrupt();
}//pass()
public static synchronized void fail()
{
//test writer didn't specify why test failed, so give generic
fail( "it just plain failed! :-)" );
}
public static synchronized void fail( String whyFailed )
{
Sysout.println( "The test failed: " + whyFailed );
Sysout.println( "The test is over, hit Ctl-C to stop Java VM" );
//check if this called from main thread
if ( mainThread == Thread.currentThread() )
{
//If main thread, fail now 'cause not sleeping
throw new RuntimeException( whyFailed );
}
theTestPassed = false;
testGeneratedInterrupt = true;
failureMessage = whyFailed;
mainThread.interrupt();
}//fail()
}// class PropertyChangeListenerLockSerialization
//This exception is used to exit from any level of call nesting
// when it's determined that the test has passed, and immediately
// end the test.
class TestPassedException extends RuntimeException
{
}
//*********** End Standard Test Machinery Section **********
//************ Begin classes defined for the test ****************
// if want to make listeners, here is the recommended place for them, then instantiate
// them in init()
/* Example of a class which may be written as part of a test
class NewClass implements anInterface
{
static int newVar = 0;
public void eventDispatched(AWTEvent e)
{
//Counting events to see if we get enough
eventCount++;
if( eventCount == 20 )
{
//got enough events, so pass
PropertyChangeListenerLockSerialization.pass();
}
else if( tries == 20 )
{
//tried too many times without getting enough events so fail
PropertyChangeListenerLockSerialization.fail();
}
}// eventDispatched()
}// NewClass class
*/
//************** End classes defined for the test *******************
/****************************************************
Standard Test Machinery
DO NOT modify anything below -- it's a standard
chunk of code whose purpose is to make user
interaction uniform, and thereby make it simpler
to read and understand someone else's test.
****************************************************/
/**
This is part of the standard test machinery.
It creates a dialog (with the instructions), and is the interface
for sending text messages to the user.
To print the instructions, send an array of strings to Sysout.createDialog
WithInstructions method. Put one line of instructions per array entry.
To display a message for the tester to see, simply call Sysout.println
with the string to be displayed.
This mimics System.out.println but works within the test harness as well
as standalone.
*/
class Sysout
{
private static TestDialog dialog;
public static void createDialogWithInstructions( String[] instructions )
{
dialog = new TestDialog( new Frame(), "Instructions" );
dialog.printInstructions( instructions );
dialog.setVisible(true);
println( "Any messages for the tester will display here." );
}
public static void createDialog( )
{
dialog = new TestDialog( new Frame(), "Instructions" );
String[] defInstr = { "Instructions will appear here. ", "" } ;
dialog.printInstructions( defInstr );
dialog.setVisible(true);
println( "Any messages for the tester will display here." );
}
public static void printInstructions( String[] instructions )
{
dialog.printInstructions( instructions );
}
public static void println( String messageIn )
{
dialog.displayMessage( messageIn );
System.out.println(messageIn);
}
}// Sysout class
/**
This is part of the standard test machinery. It provides a place for the
test instructions to be displayed, and a place for interactive messages
to the user to be displayed.
To have the test instructions displayed, see Sysout.
To have a message to the user be displayed, see Sysout.
Do not call anything in this dialog directly.
*/
class TestDialog extends Dialog
{
TextArea instructionsText;
TextArea messageText;
int maxStringLength = 80;
//DO NOT call this directly, go through Sysout
public TestDialog( Frame frame, String name )
{
super( frame, name );
int scrollBoth = TextArea.SCROLLBARS_BOTH;
instructionsText = new TextArea( "", 15, maxStringLength, scrollBoth );
add( "North", instructionsText );
messageText = new TextArea( "", 5, maxStringLength, scrollBoth );
add("Center", messageText);
pack();
setVisible(true);
}// TestDialog()
//DO NOT call this directly, go through Sysout
public void printInstructions( String[] instructions )
{
//Clear out any current instructions
instructionsText.setText( "" );
//Go down array of instruction strings
String printStr, remainingStr;
for( int i=0; i < instructions.length; i++ )
{
//chop up each into pieces maxSringLength long
remainingStr = instructions[ i ];
while( remainingStr.length() > 0 )
{
//if longer than max then chop off first max chars to print
if( remainingStr.length() >= maxStringLength )
{
//Try to chop on a word boundary
int posOfSpace = remainingStr.
lastIndexOf( ' ', maxStringLength - 1 );
if( posOfSpace <= 0 ) posOfSpace = maxStringLength - 1;
printStr = remainingStr.substring( 0, posOfSpace + 1 );
remainingStr = remainingStr.substring( posOfSpace + 1 );
}
//else just print
else
{
printStr = remainingStr;
remainingStr = "";
}
instructionsText.append( printStr + "\n" );
}// while
}// for
}//printInstructions()
//DO NOT call this directly, go through Sysout
public void displayMessage( String messageIn )
{
messageText.append( messageIn + "\n" );
System.out.println(messageIn);
}
}// TestDialog class

@ -0,0 +1,64 @@
/*
* Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
* CA 95054 USA or visit www.sun.com if you need additional information or
* have any questions.
*/
/*
test
@bug 6193279
@summary REGRESSION: AppletViewer throws IOException when path is encoded URL
@author Dmitry Cherepanov: area=appletviewer
@run compile IOExceptionIfEncodedURLTest.java
@run main IOExceptionIfEncodedURLTest
@run shell IOExceptionIfEncodedURLTest.sh
*/
import java.applet.Applet;
import sun.net.www.ParseUtil;
import java.io.File;
import java.net.MalformedURLException;
public class IOExceptionIfEncodedURLTest extends Applet{
public void init(){
}
public void start(){
// We check that appletviewer writes this message to log file
System.err.println("the appletviewer started");
}
// We expect that sun.net.www.ParseUtil.fileToEncodedURL works like following
// if relative file URL, like this "file:index.html" is processed
static String url = "file:IOExceptionIfEncodedURLTest.java";
public static final void main(String args[])
throws MalformedURLException{
System.err.println("prior checking...");
String prefix = "file:";
String path = ParseUtil.fileToEncodedURL(new File(System.getProperty("user.dir"))).getPath();
String filename = url.substring(prefix.length());
System.err.println("url="+url+" -> path="+path+",filename="+filename);
if (!path.endsWith("/") && !filename.startsWith("/")) {
throw new RuntimeException("Incorrect '/' processing");
}
}
}

@ -0,0 +1,231 @@
#
# Copyright 2008 Sun Microsystems, Inc. All Rights Reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation. Sun designates this
# particular file as subject to the "Classpath" exception as provided
# by Sun in the LICENSE file that accompanied this code.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
# CA 95054 USA or visit www.sun.com if you need additional information or
# have any questions.
#
#!/bin/ksh -p
#
# @test IOExceptionIfEncodedURLTest.sh
# @bug 6193279 6619458
# @summary REGRESSION: AppletViewer throws IOException when path is encoded URL
# @author Dmitry Cherepanov: area=appletviewer
# @run compile IOExceptionIfEncodedURLTest.java
# @run main IOExceptionIfEncodedURLTest
# @run shell IOExceptionIfEncodedURLTest.sh
# Beginning of subroutines:
status=1
#Call this from anywhere to fail the test with an error message
# usage: fail "reason why the test failed"
fail()
{ echo "The test failed :-("
echo "$*" 1>&2
echo "exit status was $status"
exit $status
} #end of fail()
#Call this from anywhere to pass the test with a message
# usage: pass "reason why the test passed if applicable"
pass()
{ echo "The test passed!!!"
echo "$*" 1>&2
exit 0
} #end of pass()
#Call this to run the test with a file name
test()
{
${TESTJAVA}${FILESEP}bin${FILESEP}appletviewer -Xnosecurity ${URL} > err 2>&1 &
APPLET_ID=$!
sleep 15
kill -9 $APPLET_ID
# these exceptions will be thrown if the test fails
cat err | grep "I/O exception while reading"
exception=$?
if [ $exception = "0" ];
then fail "test failed for "${URL}", see err file and CRs #6193279,6329251,6376334"
fi
cat err | grep "java.lang.ClassNotFoundException"
exception=$?
if [ $exception = "0" ];
then fail "test failed for "${URL}", see err file and CRs #6193279,6329251,6376334"
fi
# the applet will log the same message
cat err | grep "the appletviewer started"
started=$?
echo $started | grep "2"
if [ $? = 0 ] ;
then fail "test failed for "${URL}": syntax errors or inaccessible files"
fi
if [ $started = "0" ];
then echo "the test passed for "${URL}
else fail "test failed for "${URL}": the appletviewer behaviour is unexpected: "$started", see err file"
fi
}
# end of subroutines
# The beginning of the script proper
# Checking for proper OS
OS=`uname -s`
case "$OS" in
SunOS )
VAR="One value for Sun"
DEFAULT_JDK=/usr/local/java/jdk1.2.1/solaris
FILESEP="/"
;;
Linux )
VAR="A different value for Linux"
DEFAULT_JDK=/usr/local/java/jdk1.4/linux-i386
FILESEP="/"
;;
Windows_95 | Windows_98 | Windows_NT | Windows_ME | CYGWIN_NT-5.1)
VAR="A different value for Win32"
DEFAULT_JDK=/usr/local/java/jdk1.2.1/win32
FILESEP="\\"
;;
# catch all other OSs
* )
echo "Unrecognized system! $OS"
fail "Unrecognized system! $OS"
;;
esac
# 6438730: Only a minimal set of env variables are set for shell tests.
# To guarantee that env variable holds correct value we need to set it ourselves.
if [ -z "${PWD}" ] ; then
PWD=`pwd`
fi
# check that some executable or other file you need is available, abort if not
# note that the name of the executable is in the fail string as well.
# this is how to check for presence of the compiler, etc.
#RESOURCE=`whence SomeProgramOrFileNeeded`
#if [ "${RESOURCE}" = "" ] ;
# then fail "Need SomeProgramOrFileNeeded to perform the test" ;
#fi
# Want this test to run standalone as well as in the harness, so do the
# following to copy the test's directory into the harness's scratch directory
# and set all appropriate variables:
if [ -z "${TESTJAVA}" ] ; then
# TESTJAVA is not set, so the test is running stand-alone.
# TESTJAVA holds the path to the root directory of the build of the JDK
# to be tested. That is, any java files run explicitly in this shell
# should use TESTJAVA in the path to the java interpreter.
# So, we'll set this to the JDK spec'd on the command line. If none
# is given on the command line, tell the user that and use a cheesy
# default.
# THIS IS THE JDK BEING TESTED.
if [ -n "$1" ] ;
then TESTJAVA=$1
else echo "no JDK specified on command line so using default!"
TESTJAVA=$DEFAULT_JDK
fi
TESTSRC=.
TESTCLASSES=.
STANDALONE=1;
fi
echo "JDK under test is: $TESTJAVA"
#Deal with .class files:
if [ -n "${STANDALONE}" ] ;
then
#if standalone, remind user to cd to dir. containing test before running it
echo "Just a reminder: cd to the dir containing this test when running it"
# then compile all .java files (if there are any) into .class files
if [ -a *.java ] ;
then echo "Reminder, this test should be in its own directory with all"
echo "supporting files it needs in the directory with it."
${TESTJAVA}/bin/javac ./*.java ;
fi
# else in harness so copy all the class files from where jtreg put them
# over to the scratch directory this test is running in.
else cp ${TESTCLASSES}/*.class . ;
fi
#if in test harness, then copy the entire directory that the test is in over
# to the scratch directory. This catches any support files needed by the test.
#if [ -z "${STANDALONE}" ] ;
# then cp ${TESTSRC}/* .
#fi
#Just before executing anything, make sure it has executable permission!
chmod 777 ./*
############### YOUR TEST CODE HERE!!!!!!! #############
#All files required for the test should be in the same directory with
# this file. If converting a standalone test to run with the harness,
# as long as all files are in the same directory and it returns 0 for
# pass, you should be able to cut and paste it into here and it will
# run with the test harness.
# This is an example of running something -- test
# The stuff below catches the exit status of test then passes or fails
# this shell test as appropriate ( 0 status is considered a pass here )
# The test verifies that appletviewer correctly works with the different
# names of the files, including relative and absolute paths
# 6619458: exclude left brace from the name of the files managed by the VCS
NAME='test.html'
ENCODED='te%7Bst.html'
UNENCODED='te{st.html'
# Copy needed files into the harness's scratch directory
# or create a copy with the required name if the test is
# running as stand-alone
cp ${TESTSRC}${FILESEP}${NAME} ${UNENCODED}
# the encoded name, the path is absolute
URL="file:"${PWD}${FILESEP}${ENCODED}
test
# the encoded name, the path is relative
URL="file:"${ENCODED}
test
# the unencoded name, the path is absolute
URL="file:"${PWD}${FILESEP}${UNENCODED}
test
# the unencoded name, the path is relative
URL="file:"${UNENCODED}
test
# pick up our toys from the scratch directory
rm ${UNENCODED}

@ -0,0 +1,21 @@
<html>
<!--
test
@bug 6193279
@summary REGRESSION: AppletViewer throws IOException when path is encoded URL
@author Dmitry.Cherepanov@SUN.COM : area=appletviewer
@run compile IOExceptionIfEncodedURLTest.java
@run shell IOExceptionIfEncodedURLTest.sh
-->
<head>
<title>Started by shell script</title>
</head>
<body>
<h1>IOExceptionIfEncodedURLTest<br>Bug ID: 6193279</h1>
<p> See the dialog box (usually in upper left corner) for instructions</p>
<APPLET CODE="IOExceptionIfEncodedURLTest.class" WIDTH=200 HEIGHT=200></APPLET>
</body>
</html>