// AppletTst1.java /* ** Licensed Materials - Property of IBM ** ** (C) COPYRIGHT IBM Corp. 1996, 1997 All rights reserved ** ** US Government Users Restricted Rights - Use, duplication or ** disclosure restricted by GSA ADP Schedule Contract with IBM Corp. ** **/ package com.ibm.tspaces.examples.simple; import java.awt.event.*; import java.awt.*; import java.applet.*; import java.net.*; import com.ibm.tspaces.*; /** ** This class implements a simple Applet that ** interfaces with TSpaces. **
** Some things to note: ** - It ensures that only one instance of the applet is ** is running. ** - It uses the destroy() interface to cleanup the connection ** to the server. ** **** @version $Revision: 1.1.2.2 $ $Date: 2000/02/05 14:50:43 $ ** @author John Thomas */ public class AppletTst1 extends Applet implements Callback, Runnable{ /** ** true if running as an application */ private static boolean application = false; /** ** Number of instances of this class under this JVM */ private static int _instanceCount = 0; /** ** This will be set true when start() called and ** set to false when stop() is called; */ protected static boolean _started = false; protected static final int WIDTH = 240; protected static final int HEIGHT = 300; public Frame appFrame; /** ** This holds a reference to the current TupleSpace. */ protected TupleSpace _ts = null; protected static Color BACKGROUND_COLOR = Color.white; /** ** This is the Host where the TupleSpace Server is running */ protected static String _host = TupleSpace.DEFAULTHOST; protected static int _port = TupleSpace.DEFAULTPORT; /** ** The Space name */ protected static String _tsName = "AppletTst1"; private boolean _failed = false; String _msg = "Unknown error"; /** ** Sequence number assigned to EventRegister */ private int _seqNum = -1; /* *************************************************************************** ** ** constructor ** ** ********** */ /** ** The default constructor. ** ** The constructor has little use in an applet but ** we have one just for completeness. ** ** *************************************************************************** */ public AppletTst1() { Debug.out("Constructor entered"); } /* *************************************************************************** ** ** init ** ** ********** */ /** ** Initialization: ** This could be entered automatically when running as an applet ** or by being called from main() is being run from an ** application. ** ** This is where all of the window and TSpace setup is done ** Note that we increment a static variable (_instanceCount) to ** keep track of how many instances of this applet are running ** *************************************************************************** */ public void init() { Debug.setDebugOn(true); TupleSpace.setDebug(true); Debug.out("AppletTst1 init() "); if (application) { // Running as an application appFrame = new Frame("TSpaces Applet Test"); appFrame.add("Center", this); appFrame.setSize(WIDTH,HEIGHT); } else { // Running as an applet Component c = this.getParent(); while (c != null && ! (c instanceof Frame)) c = c.getParent(); appFrame = (Frame)c; Debug.out("appFrame="+appFrame); // We will assume that Tuplespace is on same host as applet codebase URL url = getCodeBase(); String urlhost = url.getHost(); Debug.out("Host="+urlhost); if (urlhost.length() != 0) _host = urlhost; } this.setLayout(new BorderLayout()); if (_instanceCount > 0 ) { _failed = true; _msg = "Applet already active. Only one allowed"; } else { _instanceCount++; // keep track of how many are started setupButtons(this); } if (_failed) { Label err = new Label(_msg); this.add("South",err); appFrame.show(); return; } setBackground(BACKGROUND_COLOR); // Handle the user exiting/killing the application // I don't think this can happen with an applet. if ( application && appFrame != null ) { appFrame.addWindowListener( new WindowAdapter() { public void windowClosing (WindowEvent e) { Debug.out("Window Close event"); destroy(); System.exit(0); } } ); } Debug.out("Access tuplespace at " + _host); String user = TupleSpace._DEFAULT_USER; String pass = TupleSpace._DEFAULT_PASSWORD; // Tell the TupleSpace code that we are going to be running // in an applet sandbox and to avoid any otion that is // invalid. TupleSpace.appletEnvironment(true); String version = TupleSpace.getVersion(); Debug.out("TSpaces Version="+version); try { // Verify that the Server is active Tuple active = TupleSpace.status(_host,_port); Debug.out("Status="+active); // status() returns a simple Tuple that contains "Running" or "NotRunning" if ( active == null || active.getField(0).getValue().equals("NotRunning") ) { _msg = "TSpaces server not running on " + _host; Debug.out(_msg); _failed = true; } } catch (TupleSpaceException tse) { _failed = true; _msg = tse.getMessage(); Debug.out(tse); } TupleSpace.setConnectionTries(1); if (!_failed) { _failed = ! setupTS(); } if (_failed ) { Label errmsg = new Label("Failure: "+ _msg); appFrame.add("South",errmsg); appFrame.setVisible(true); return; } appFrame.setVisible(true); } // init /************************************************************************** ** ** setupButtons ** ** ********** */ /** ** sets up some buttons that user can poke at ** Currently it only creates a "Write" button that ** causes a tuple to be written. ** *************************************************************************** */ public void setupButtons(Panel appPanel) { appPanel.setLayout(new BorderLayout()); Debug.out("setupButtons()"); Button writeButton = new Button("WRITE"); writeButton.addActionListener( new ActionListener() { public void actionPerformed(ActionEvent e) { try { // May have done destroy in another window if (_ts == null) setupTS(); if (_ts != null) { _ts.write("Write it"); Debug.out("Write it"); } else { Debug.out("Write bypassed, _ts == null"); } } catch (TupleSpaceException tse) { Debug.out(tse.getMessage()); _ts = null; } catch (Exception ex) { Debug.out(ex); } } } ); appPanel.add("Center",writeButton); return; } /************************************************************************** ** ** setupTS ** ** ********** */ /** ** setup for TSpaces access ** ** @return true if the setup is OK *************************************************************************** */ public boolean setupTS() { Debug.out("setupTS()"); try { //-------------------------------------------------- // Setup to access TupleSpace // We access the tuplespace on the indicatd host. // // We then just register for the write event // we must implement Callback which will the call() method to // be called anytime anyone writes a matching tuple to the tuplespace //------------------------------------------------------------ Debug.out("_ts="+_ts); _ts = new TupleSpace(_tsName, _host); // create a template to indicate what we are interested in Tuple match = new Tuple(); _seqNum = _ts.eventRegister(TupleSpace.WRITE,match, this); Debug.out("EventRegister() seqNum="+_seqNum); //_ts.write("TestWrite"); } catch(TupleSpaceException tse) { Debug.out(tse); _msg = tse.getMessage(); return false; } return true; } // setupTS /* *************************************************************************** ** ** run ** ** ********** */ /** ** run: Is entered as as a result of a start thread ** It is not currently being used. ** *************************************************************************** */ public void run() { Debug.out("run()"); while (true) { try { Thread.currentThread().sleep(5000); } catch (InterruptedException ie) {} } } /* *************************************************************************** ** ** paint ** ** ********** */ /** ** paint() is called to redisplay ** ** *************************************************************************** */ public void paint(Graphics g) { Debug.out("paint()"); } /* *************************************************************************** ** ** start ** ** ********** */ /** ** start() is called when it is time for the applet to start doing stuff. ** ** This could be called multiple times as the applet is stopped and started. ** If the TupleSpace setup has been terminated, then it will be ** restarted. ** *************************************************************************** */ public void start() { Debug.out("start()"); _started = true; if (_ts == null && !_failed ) { setupTS(); } } /* *************************************************************************** ** ** stop ** ** ********** */ /** ** stop() is called when the applet is no longer visible so we no longer need to ** keep painting the screen, but we should still listen for events. ** ** This could be called multiple times as the applet is stopped and started. ** ** Since the startup will reinit the TupleSpace environment, ** we can issue a cleanup() here but only if there are ** no other active instances. *************************************************************************** */ public void stop() { Debug.out("stop()"); _started = false; /**** if (_instanceCount == 1) { TupleSpace.cleanup(_ts.getServer(),_ts.getPort()); _ts = null; Debug.out("TupleSpace connections terminated"); } ****/ } /* *************************************************************************** ** ** destroy ** ** ********** */ /** ** destroy() is called when the applet is going to be permanently stoped ** ** We will decrement the instance count and if it is now zero ** we will cleanup the TSpaces connection. *************************************************************************** */ public void destroy() { Debug.out("destroy()"); if (_failed) return; _instanceCount--; // This instance will disappear. if (_instanceCount == 0) { try { _ts.eventDeRegister(_seqNum); Debug.out("events deregistered: "+_seqNum); } catch (TupleSpaceException tse) { Debug.out(tse); } TupleSpace.cleanup(_ts.getServer(),_ts.getPort()); _ts = null; Debug.out("cleanup done"); } else { Debug.out("cleanup() bypassed"); } } /* *************************************************************************** ** ** call ** ** ********** */ /** ** Process the callback from the server that notifies us when anyone ** (including ourselves) writes to the TupleSpace. ** ** @param eventName_ the name of the event command that caused this call, that is the ** name of the client side command of the thread that registered this call, e.g., in the ** case of a read, this would be TupleSpace.READ, **not** TupleSpace.WRITE which is the ** corresponding command that caused the actaul event. ** @param tsName_ the name of the tuple space this command was executed on. ** @param sequenceNumber_ the sequenceNumber for this event/command ** @param tuple_ the returned tuple or a Tuple with an exception inside ** @param isException_ was the command processed normaly or was there an exception ** ** @return true if this is the last call this sequence # should be getting otherwise false *************************************************************************** */ public synchronized boolean call(String eventName_, String tsName_, int sequenceNumber_, SuperTuple tuple_, boolean isException_) { try { Debug.out("callback for " + eventName_ + ", TupleSpace = " + tsName_ + ",Seq #=" + sequenceNumber_ + ",Tuple=" + tuple_ + ", isException=" + isException_); if (isException_) { Throwable t = (Throwable)tuple_.getField(0).getValue(); Debug.out(0,t); return true; } } catch (Exception e) { Debug.out(e); } return false; } // call /* *************************************************************************** ** ** main ** ** ********** */ /** ** Run the AppletTst1 as an application. ** ** @param args - command line arguments *************************************************************************** */ public static void main(String args[]) { AppletTst1 appletTst1; try { Debug.setDebugOn(true); application = true; if(args.length >= 1) _host = args[0]; appletTst1 = new AppletTst1(); appletTst1.init(); appletTst1.start(); Thread.sleep(1000); appletTst1.stop(); Thread.sleep(5000); appletTst1.destroy(); } catch (Exception e) { Debug.out(e); } } // main } // AppletTst1 /* $Log: AppletTst1.java,v $ Revision 1.1.2.2 2000/02/05 14:50:43 jthomas no message Revision 1.1.2.1 2000/01/28 18:17:59 jthomas New applet example Revision 1.1.2.2 2000/01/24 20:33:20 jthomas changed so that it can handle multiple instances in the same browser Revision 1.1.2.1 2000/01/17 17:10:47 jthomas no message /* */