//----------------------------------------------------------------------------- // Copyright (c) 1994,1995 Southeastern Universities Research Association, // Continuous Electron Beam Accelerator Facility // // This software was developed under a United States Government license // described in the NOTICE file included as part of this distribution. // // Jefferson Lab HPC Group, 12000 Jefferson Ave., Newport News, VA 23606 //----------------------------------------------------------------------------- // // Description: // Core part of rsvcClient Java Package // // Author: // Jie Chen // Jefferson Lab HPC Group // // Revision History: // $Log: rsvcClient.java,v $ // Revision 1.1.1.1 2000/05/23 15:12:50 pal // cdev_psi_1.7.2 // // Revision 1.1 1999/10/18 17:12:39 chen // *** empty log message *** // // // import rsvcData; import rsvcEvent; import rsvcConfig; import rsvcEventHandler; import rsvcClientReader; import java.io.*; import java.net.*; import java.util.*; public final class rsvcClient { // connection flag private boolean connected_ = false; // Socket to the server private Socket tcpsocket_ = null; // server information private String server_host_ = null; private int server_port_ = 0; // internal request id private int eventid_ = 1234; // internal client data reader private rsvcClientReader reader_ = null; // internal thread id for reader private Thread readerthread_ = null; // output stream private OutputStream output_ = null; /** * Construct an empty rsvcClient object */ public rsvcClient () { // empty } /** * Override default finalize method.This allows Java virtual * machine to clean up resource when this object is no longer * needed. */ protected void finalize() throws Throwable { if (tcpsocket_ != null && connected_ == true) { connected_ = false; tcpsocket_.close (); } } /** * Connect to a server that is on a given host at a given port */ public synchronized void connect (String host, int port) throws UnknownHostException, IOException { try { tcpsocket_ = new Socket (host, port); }catch (UnknownHostException ue){ System.err.println (ue); throw ue; }catch (IOException e) { System.err.println(e); throw e; } // set connection flag connected_ = true; // cache server information server_host_ = new String(host); server_port_ = port; OutputStream toutput = null; try { toutput = tcpsocket_.getOutputStream(); }catch (IOException e) { System.err.println (e); throw e; } output_ = toutput; // create a single rsvcClient Data Reader and spawn a new thread reader_ = new rsvcClientReader (this); readerthread_ = new Thread (reader_); readerthread_.start (); } /** * Return underlying socket */ public Socket getSocket () throws NullPointerException { if (tcpsocket_ == null) throw new NullPointerException ("Socket is invalid"); return tcpsocket_; } /** * Return underlying reader thread */ public Thread getReaderThread () throws NullPointerException { if (readerthread_ == null) throw new NullPointerException ("Reader Thread is not alive"); return readerthread_; } /** * Disconnect from the server */ public synchronized void disconnect () throws IOException { if (tcpsocket_ == null || connected_ == false) throw new IOException ("Socket is not connected to the server"); try { tcpsocket_.close(); }catch (IOException e) { throw e; } connected_ = false; // remove all event handlers reader_.cleanupEventHandlers (); } /** * Is connection established */ public boolean connected () { return connected_; } /** * Register an event handler to handle disconnection event */ public synchronized boolean addDisconnectHandler (rsvcEventHandler handler) { return reader_.addDisconnectHandler (handler); } /** * Handle server unexpected close */ public int handleClose () { try { tcpsocket_.close (); } catch (IOException e) { System.err.println (e); connected_ = false; return -1; } connected_ = false; reader_.dispatchDiscEventHandlers (); // clean up all callbacks reader_.cleanupEventHandlers (); return 0; } /** * Create a memory based database with an event handler. * Data coming back to the event handler contain table definition */ public rsvcEvent createMemDbase (String tablename, rsvcData data, rsvcEventHandler handler) throws IOException { rsvcEvent id = null; data.insert (rsvcConfig.RSVC_TABLE_NAME, tablename); try { id = sendCommand (rsvcConfig.RSVC_CREATE_MEMTABLE, data, handler); }catch (IOException e) { throw e; } return id; } /** * Open a database with a given name using an event handler. * Data retured to the event handler contain definition of database */ public rsvcEvent openDatabase (String name, rsvcData data, rsvcEventHandler handler) throws IOException { rsvcEvent id = null; data.insert (rsvcConfig.RSVC_TABLE_NAME, name); try { id = sendCommand (rsvcConfig.RSVC_OPEN_DBASE, data, handler); }catch (IOException e) { throw e; } return id; } /** * Insert data into a database with a given name. * The last argument 'overwrite = 1' selects whether to overwite * existing items in the database. * Data must match table definition returned from the openDatabase call. */ public rsvcEvent insertValue (String name, rsvcData data, rsvcEventHandler handler, boolean overwrite) throws IOException { rsvcEvent id = null; data.insert (rsvcConfig.RSVC_TABLE_NAME, name); if (overwrite == true) { try { id = sendCommand (rsvcConfig.RSVC_OVERWRITE, data, handler); }catch (IOException e) { throw e; } } else { try { id = sendCommand (rsvcConfig.RSVC_INSERT, data, handler); }catch (IOException e) { throw e; } } return id; } /** * Get data out from the database with a given name. * Outbound data either contain a tagged value to denote a key value * such as : "id", "model+gold" or contain multiple tagged values that * can be constructed into a key value */ public rsvcEvent getValue (String name, rsvcData data, rsvcEventHandler handler) throws IOException { rsvcEvent id = null; data.insert (rsvcConfig.RSVC_TABLE_NAME, name); try { id = sendCommand (rsvcConfig.RSVC_GET, data, handler); }catch (IOException e) { throw e; } return id; } /** * Delete a data item from the database with a given name. * Outbound data either contain a tagged value to denote a key value * such as : "id", "model+gold" or contain multiple tagged values that * can be constructed into a key value */ public rsvcEvent delValue (String name, rsvcData data, rsvcEventHandler handler) throws IOException { rsvcEvent id = null; data.insert (rsvcConfig.RSVC_TABLE_NAME, name); try { id = sendCommand (rsvcConfig.RSVC_DEL, data, handler); }catch (IOException e) { throw e; } return id; } /** * Set value for a datum inside database with a given name. * The outbound data item either contain a tagged value to denote * a index value e.g.: "id", "model+gold" * or contains multiple tagged values which can be constructed * into a key value * plus a subset of tagged values defined in the table definition */ public rsvcEvent setValue (String name, rsvcData data, rsvcEventHandler handler) throws IOException { rsvcEvent id = null; data.insert (rsvcConfig.RSVC_TABLE_NAME, name); try { id = sendCommand (rsvcConfig.RSVC_SET, data, handler); }catch (IOException e) { throw e; } return id; } /** * Monitor on a data item inside a database with a given name. * Any changes to this item will trigger an event coming back. * The outbound data either contain a tagged value to denote a index value * Example: "id", "model+gold" * or contains multiple tagged values which can be constructed * into a key value. */ public rsvcEvent monitorValue (String name, rsvcData data, rsvcEventHandler handler) throws IOException { rsvcEvent id = null; data.insert (rsvcConfig.RSVC_TABLE_NAME, name); try { id = sendMonitor (rsvcConfig.RSVC_MONITOR_ON, data, handler); } catch (IOException e) { throw e; } return id; } /** * Monitor off a data inside a database with a given name * Outbound data either contain a tagged value to denote a index value * Example: "id", "model+gold" * or contains multiple tagged values which can be constructed * into a key value. */ public rsvcEvent monitorOffValue (String name, rsvcData data, rsvcEvent mid) throws IOException { rsvcEvent id = null; data.insert (rsvcConfig.RSVC_TABLE_NAME, name); try { id = sendMonitorOff (rsvcConfig.RSVC_MONITOR_OFF, data, mid); } catch (IOException e) { throw e; } return id; } /** * monitor a single attribute of a data inside a database with a given name. * any changes to this attribute will trigger an event. * Data coming back to the event handler containing a whole data. * Outbound data either contain a tagged value to denote a index value * Example: "id", "model+gold" * or contains multiple tagged values which can be constructed * into a key value */ public rsvcEvent monitorAttr (String name, String attr, rsvcData data, rsvcEventHandler handler) throws IOException { rsvcEvent id = null; data.insert (rsvcConfig.RSVC_TABLE_NAME, name); data.insert (rsvcConfig.RSVC_MONITOR_TAG, attr); try { id = sendMonitor (rsvcConfig.RSVC_MONITOR_ONATTR, data, handler); } catch (IOException e) { throw e; } return id; } /** * Stop monitoring a single attribute of a data inside a database. * Outbound data either contain a tagged value to denote a index value * Example: "id", "model+gold" * or contains multiple tagged values which can be constructed * into a key value . */ public rsvcEvent monitorOffAttr (String name, String attr, rsvcData data, rsvcEvent mid) throws IOException { rsvcEvent id = null; data.insert (rsvcConfig.RSVC_TABLE_NAME, name); data.insert (rsvcConfig.RSVC_MONITOR_TAG, attr); try { id = sendMonitorOff (rsvcConfig.RSVC_MONITOR_OFFATTR, data, mid); } catch (IOException e) { throw e; } return id; } /** * query a particular database 'name' * query msg can be like regular C logic expression for all * attributes. */ public rsvcEvent query (String name, String qmsg, rsvcEventHandler handler) throws IOException { rsvcEvent id = null; rsvcData data = new rsvcData (); data.insert (rsvcConfig.RSVC_TABLE_NAME, name); data.insert (rsvcConfig.RSVC_QUERY_TAG, qmsg); try { id = sendCommand (rsvcConfig.RSVC_QUERY, data, handler); }catch (IOException e) { throw e; } return id; } /** * Monitor incoming entries inside database * any insertion to a database will trigger an event */ public rsvcEvent monitorIncomingEntries (String name, rsvcData data, rsvcEventHandler handler) throws IOException { rsvcEvent id = null; data.insert (rsvcConfig.RSVC_TABLE_NAME, name); try { id = sendMonitor (rsvcConfig.RSVC_MONITOR_ENTRIES, data, handler); } catch (IOException e) { throw e; } return id; } /** * Stop monitoring the incoming entries inside database. */ public rsvcEvent monitorOffIncomingEntries (String name, rsvcData data, rsvcEvent mid) throws IOException { rsvcEvent id = null; data.insert (rsvcConfig.RSVC_TABLE_NAME, name); try { id = sendMonitorOff(rsvcConfig.RSVC_MONITOR_OFFENTRIES, data, mid); }catch (IOException e) { throw e; } return id; } /** * Generic monitor on command */ private synchronized rsvcEvent sendMonitor (int opcode, rsvcData data, rsvcEventHandler handler) throws IOException { int status = rsvcConfig.RSVC_SUCCESS; // create an event that is being shipped to server rsvcEvent cbk = new rsvcEvent (data); cbk.setEventid (eventid_); cbk.setOpcode (opcode); // write this event to server int len = cbk.streamSize (); // create a buffered data output BufferedOutputStream boutput = new BufferedOutputStream (output_, len); try { cbk.streamOut (boutput); }catch (IOException e) { System.err.println (e); status = rsvcConfig.RSVC_IOFAILED; throw e; } if (status == rsvcConfig.RSVC_SUCCESS) { try { boutput.flush (); }catch (IOException e) { System.err.println (e); status = rsvcConfig.RSVC_IOFAILED; throw e; } } if (status == rsvcConfig.RSVC_SUCCESS) { cbk.setHandler (handler); reader_.addMonitorEventHandler (eventid_, cbk); } eventid_ ++; return cbk; } /** * Generic monitor on command */ private synchronized rsvcEvent sendMonitorOff (int opcode, rsvcData data, rsvcEvent monitorEvent) throws IOException { int status = rsvcConfig.RSVC_SUCCESS; if (reader_.containsMonitorEvent (monitorEvent) != true) { throw new IOException ("Monitor Off using an invalid event"); } // create new event with differen opcode rsvcEvent cbk = new rsvcEvent (monitorEvent); cbk.setOpcode (opcode); // write this event to server int len = cbk.streamSize (); // create a buffered data output BufferedOutputStream boutput = new BufferedOutputStream (output_, len); try { cbk.streamOut (boutput); }catch (IOException e) { System.err.println (e); status = rsvcConfig.RSVC_IOFAILED; throw e; } if (status == rsvcConfig.RSVC_SUCCESS) { try { boutput.flush (); }catch (IOException e) { System.err.println (e); status = rsvcConfig.RSVC_IOFAILED; throw e; } } return cbk; } /** * Generic command call with ith an event handler. * Data coming back to the event handler contain table definition */ private synchronized rsvcEvent sendCommand (int opcode, rsvcData data, rsvcEventHandler handler) throws IOException { int status = rsvcConfig.RSVC_SUCCESS; // create an event that is being shipped to server rsvcEvent cbk = new rsvcEvent (data); cbk.setEventid (eventid_); cbk.setOpcode (opcode); // write this event to server int len = cbk.streamSize (); // create a buffered data output BufferedOutputStream boutput = new BufferedOutputStream (output_, len); try { cbk.streamOut (boutput); }catch (IOException e) { System.err.println (e); status = rsvcConfig.RSVC_IOFAILED; throw e; } if (status == rsvcConfig.RSVC_SUCCESS) { try { boutput.flush (); }catch (IOException e) { System.err.println (e); status = rsvcConfig.RSVC_IOFAILED; throw e; } } if (status == rsvcConfig.RSVC_SUCCESS) { cbk.setHandler (handler); reader_.addCommandEventHandler (eventid_, cbk); } eventid_ ++; return cbk; } }