1 package uk.ac.vamsas.test;
3 import uk.ac.vamsas.client.*;
4 import uk.ac.vamsas.client.picking.IMessageHandler;
5 import uk.ac.vamsas.client.picking.IPickManager;
6 import uk.ac.vamsas.client.picking.Message;
7 import uk.ac.vamsas.objects.core.VAMSAS;
8 import uk.ac.vamsas.test.objects.Core;
10 import java.awt.Event;
11 import java.beans.PropertyChangeEvent;
12 import java.beans.PropertyChangeListener;
13 import java.io.DataInput;
14 import java.io.DataInputStream;
15 import java.io.DataOutputStream;
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.io.ObjectInputStream;
20 import java.io.ObjectOutputStream;
21 import java.io.OutputStream;
22 import java.util.Vector;
25 * Toy vamsas command line client application demonstrating the API.
26 * Currently runs with one argument: ExampleApplication.main(new String("watch"))
27 * Test: Start up at least two of these processes independently and they will
28 * successively modify and handle update events from the document model.
30 * Behaviour of each client:
31 * Event handlers are registered for documentUpdate.
32 * - every document update:
33 * * the vamsas document will be dumped to standard out using uk.ac.vamsas.test.simpleclient.ArchiveReports
34 * * if there are more than 4 vamsas roots, the first sequence in the first alignment of the first dataset of the second vamsas root will be appended with a single gap character and then written back to the session document.
35 * A pick thread is started, which sends random CUSTOM pick events every so often (tuning: flooding the pick channel seems to affect the behaviour of other vamsasClient threads, suggesting some object lock contention).
36 * A new vamsas root generated from uk.ac.vamsas.test.objects.Core.getDemoVamsas is added to the document.
37 * Then a while loop waits around for events until shutdown:
38 * - currently it will shutdown after 9 updates (totalUpdates)
39 * - an update will be made after every other update that is detected.
41 * Status: PickManager now shuts down correctly. Serial updates for two
42 * instances work correctly and are detected under j1.4 (need to test in 1.5 and
45 * TODO: test appData get/set methods
47 * TODO: verify and test pickManager and interaction between it and other
50 * TODO: add more session interaction events
52 * TODO: test client add/leave events - currently library generates exceptions
53 * for sessionlist and clientlist modifications.
58 public class ExampleApplication {
59 private ClientHandle app;
61 private UserHandle user; // TODO: make this something defined by the
65 private IClientFactory clientfactory;
67 private IClient vorbaclient;
69 private byte[] mydata;
71 private Vector vamsasObjects;
73 private boolean isUpdated = false;
75 private boolean isShuttingdown = false;
77 private boolean isFinalizing = false;
79 private int totalUpdates = 9;
81 private uk.ac.vamsas.client.VorbaId recover = null;
83 private int calls = 0;
85 private long mdatahash = 0;
87 private long muserdatahash = 0;
89 private void processVamsasDocument(IClientDocument doc) {
90 if (doc.getVamsasRoots().length < 4) {
91 doc.addVamsasRoot(Core.getDemoVamsas());
94 uk.ac.vamsas.objects.core.DataSet ds = doc.getVamsasRoots()[1]
96 uk.ac.vamsas.objects.core.AlignmentSequence alsq = ds.getAlignment(0)
97 .getAlignmentSequence(0);
98 if (recover == null) {
99 recover = alsq.getVorbaId();
101 Vobject recoverd = doc.getObject(recover);
102 System.out.println("Recovery of " + recover + " was "
103 + ((recoverd == null) ? "A FAILURE" : "SUCCESSFUL"));
105 System.out.println("Modifying Sequence:\n" + alsq.hashCode());
106 alsq.setSequence(alsq.getSequence() + ds.getAlignment(0).getGapChar());
107 System.out.println("Modifying Sequence:\n" + alsq.hashCode());
108 System.out.println("Modified Sequence:\n" + alsq.getSequence());
109 doc.setVamsasRoots(doc.getVamsasRoots());
110 } catch (Exception ee) {
114 // get this apps 'mydata' if it hasn't got it already.
115 System.out.println("Trying to get appdata and modify it.....");
118 System.out.println(".....Finished.");
119 } catch (Exception e) {
120 System.err.println("Failed to process appdata for our application.");
121 e.printStackTrace(System.err);
124 // .. access this application's 'public' mydata' if there is any.
125 vorbaclient.updateDocument(doc);
126 // merge vamsasObjects with vamsas objects in document
130 private int appdatareads = 0;
132 private void processAppData(IClientDocument doc) throws Exception {
134 boolean writtenonce = false;
136 uk.ac.vamsas.client.IClientAppdata appd = doc.getClientAppdata();
137 if (appd.hasClientAppdata() && !(appdatareads % 2 == 0)) {
138 // byte[] cappd = appd.getClientAppdata();
140 // System.out.println("Client appdata\n"+cappd.toString()+"\nEnd of
142 System.out.println("Testing read from inputstream");
143 String cappds = readData(appd.getClientInputStream());
144 System.out.println("Client appdata\n" + cappds + "\nEnd of Appdata\n");
147 String newapd = "Client Appdata:";
148 if (appd.hasClientAppdata())
150 AppDataInputStream is;
151 newapd = readData(is = appd.getClientInputStream());
155 // appd.setClientAppdata(makeappData("Client Appdata for
156 // "+user.toString()+" written"));
157 writeData(appd.getClientOutputStream(),
158 newapd+" : Client Appdata for all users written on " + appdatareads
159 + " read by " + vorbaclient.getUserHandle());
160 System.out.println("Written to ClientAppdata stream.");
163 if (appd.hasUserAppdata() && !(appdatareads % 2 == 0)) {
164 byte[] cappd = appd.getUserAppdata();
166 System.out.println("User appdata\n" + new String(cappd)
167 + "\nEnd of Users' Appdata\n");
169 System.out.println("No user appdata.");
170 appd.setUserAppdata(("no default - overwritten null byte set on "
171 + appdatareads + " read by " + vorbaclient.getUserHandle() + "")
174 } else if (!writtenonce) {
176 byte[] bts = makeappData("User Appdata for " + user + " written on "
177 + appdatareads + " read at ");
178 System.out.println("Setting appData bytes to\n" + new String(bts)
180 appd.setUserAppdata(bts);
181 System.out.println("Written to UserAppdata stream.");
186 private byte[] makeappData(String message) {
187 StringBuffer sb = new StringBuffer();
189 sb.append("on " + new java.util.Date());
190 return sb.toString().getBytes();
193 private boolean writeData(AppDataOutputStream os, String message) {
194 StringBuffer sb = new StringBuffer();
196 sb.append("on " + new java.util.Date());
198 ObjectOutputStream oos = new ObjectOutputStream(os);
199 oos.writeObject(sb.toString());
202 } catch (Exception e) {
203 System.err.println("Problem serialising this message:\n" + sb);
204 e.printStackTrace(System.err);
210 private String readData(AppDataInputStream is) {
213 if (is.available() > 0) {
214 ObjectInputStream ois = new ObjectInputStream(is);
215 String rs = (String) ois.readObject();
218 } catch (Exception e) {
219 System.err.println("Failed to read a string from input stream!");
220 e.printStackTrace(System.err);
226 private void addHandlers(IClient avorbaclient) {
227 final ExampleApplication me = this;
228 // make a non-volatile reference to the client instance.
229 final IClient vorbaclient = avorbaclient;
230 // register update handler
231 vorbaclient.addDocumentUpdateHandler(new PropertyChangeListener() {
232 public void propertyChange(PropertyChangeEvent evt) {
233 System.out.println("Vamsas document update for "
234 + evt.getPropertyName() + ": " + evt.getOldValue() + " to "
235 + evt.getNewValue());
236 // merge new data into ours.
237 // example - output doc
239 IClientDocument cdoc = vorbaclient.getClientDocument();
240 if (calls > 2 && cdoc.getVamsasRoots().length > 0
241 && !cdoc.getVamsasRoots()[0].is__stored_in_document()) {
243 .println("Pathological Update Detected - Document is zeroed!");
246 uk.ac.vamsas.test.simpleclient.ArchiveReports.rootReport(cdoc
247 .getVamsasRoots(), true, System.out);
250 if (cdoc.getVamsasRoots().length > 2) {
251 uk.ac.vamsas.objects.core.DataSet ds = cdoc.getVamsasRoots()[1]
253 uk.ac.vamsas.objects.core.AlignmentSequence alsq = ds
254 .getAlignment(0).getAlignmentSequence(0);
255 if (alsq.isUpdated())
256 System.out.println("Seqeuence was updated since last time.");
257 alsq.setSequence(alsq.getSequence()
258 + ds.getAlignment(0).getGapChar());
259 System.out.println("Newly Modified Sequence:\n"
260 + alsq.getSequence());
261 cdoc.setVamsasRoots(cdoc.getVamsasRoots());
263 } catch (Exception ee) {
264 System.err.println("Exception whilst updating :");
265 ee.printStackTrace(System.err);
267 vorbaclient.updateDocument(cdoc);
268 } catch (Exception e) {
270 .println("Exception whilst dumping document tree after an update.");
271 e.printStackTrace(System.err);
273 isUpdated = true; // tell main thread to reflect change...
276 // register close handler
277 vorbaclient.addVorbaEventHandler(Events.DOCUMENT_REQUESTTOCLOSE,
278 new PropertyChangeListener() {
279 public void propertyChange(PropertyChangeEvent evt) {
280 System.out.println("Received request to close vamsas document.");
281 // ask user for a filename to save it to.
282 // Then pass it to the vorba object...
283 vorbaclient.storeDocument(new java.io.File("UserLocation"));
287 // register some more handlers to monitor the session :
289 vorbaclient.addVorbaEventHandler(Events.CLIENT_CREATION,
290 new PropertyChangeListener() {
291 public void propertyChange(PropertyChangeEvent evt) {
292 System.out.println("New Vamsas client for " + evt.getPropertyName()
293 + ": " + evt.getOldValue() + " to " + evt.getNewValue());
294 // tell app add new client to its list of clients.
297 vorbaclient.addVorbaEventHandler(Events.CLIENT_FINALIZATION,
298 new PropertyChangeListener() {
299 public void propertyChange(PropertyChangeEvent evt) {
300 System.out.println("Vamsas client finalizing for "
301 + evt.getPropertyName() + ": " + evt.getOldValue() + " to "
302 + evt.getNewValue());
303 // tell app to update its list of clients to communicate
307 vorbaclient.addVorbaEventHandler(Events.SESSION_SHUTDOWN,
308 new PropertyChangeListener() {
309 public void propertyChange(PropertyChangeEvent evt) {
310 System.out.println("Session " + evt.getPropertyName()
311 + " is shutting down.");
312 // tell app to finalize its session data before
316 vorbaclient.addVorbaEventHandler(Events.DOCUMENT_FINALIZEAPPDATA,
317 new PropertyChangeListener() {
318 public void propertyChange(PropertyChangeEvent evt) {
319 boolean finalized = false;
321 .println("Application received a DOCUMENT_FINALIZEAPPDATA event.");
322 IClientDocument cdoc = null;
324 cdoc = vorbaclient.getClientDocument();
326 IClientAppdata apd = cdoc.getClientAppdata();
329 if (apd.getUserAppdata()!=null)
331 userd = new String(apd.getUserAppdata());
333 String appdat = me.readData(apd.getClientInputStream());
334 me.writeData(apd.getClientOutputStream(), appdat
335 + "\nUser Data merged\n" + userd + "\n");
338 vorbaclient.updateDocument(cdoc);
340 // tell app to finalize its session data prior to the
341 // storage of the current session as an archive.
342 } catch (Exception e) {
345 .println("Probable library problem - exception when trying to update document after writing merged appdata.");
346 e.printStackTrace(System.err);
349 .println("Recovering from exception when writing merged appdata");
350 e.printStackTrace(System.err);
353 vorbaclient.updateDocument(cdoc);
355 } catch (Exception e2) {
357 .println("Probable library problem - exception when trying to update document after an exception when writing merged appdata.");
358 e2.printStackTrace(System.err);
363 System.out.println("Application finalized appdata successfuly.");
369 public String Usage = "ExampleApplication :/n [-arena <vamsasFileDirectory>][-session <vamsasSessionURN>] <action> [+<arguments>]\n"
370 + "<action> is one of :\n\tsave,update,close,watch";
374 String importFile = null;
376 String outputFile = null;
378 private boolean parseArgs(String args[]) {
379 if (args.length == 0) {
383 boolean parsed = false;
384 while (!parsed && cpos < args.length) {
385 if (args[cpos].toLowerCase().equals("load") && cpos + 1 < args.length) {
386 importFile = args[cpos + 1];
390 if (args[cpos].toLowerCase().equals("save") && cpos + 1 < args.length) {
391 outputFile = args[cpos + 1];
395 // default behaviour - if not anything else its probably a session urn
396 if (!args[cpos].toLowerCase().equals("watch")) {
404 class ExamplePicker extends Thread {
407 public IPickManager pm = null;
409 ExamplePicker(String me, IPickManager pm) {
418 Thread.sleep(1000 + (long) Math.random() * 10000);
419 } catch (Exception e) {
423 pm.sendMessage(new uk.ac.vamsas.client.picking.CustomMessage(
424 "Message " + mcount++ + " from " + me));
433 public void runMe(String[] args) {
434 if (!parseArgs(args)) {
435 System.err.print(Usage);
437 // get IClientFactory
439 clientfactory = new uk.ac.vamsas.client.simpleclient.SimpleClientFactory();
440 } catch (IOException e) {
441 System.err.println(e + "\n" + Usage);
445 // get an Iclient with session data
446 app = new ClientHandle("uk.ac.vamsas.test.ExampleApplication", "0.1");
447 user = new UserHandle("arnolduser", "deathsdoor");
450 System.out.println("Connecting to " + sess);
451 vorbaclient = clientfactory.getIClient(app, user, sess);
453 vorbaclient = clientfactory.getIClient(app, user);
455 } catch (NoDefaultSessionException e) {
457 .println("There appear to be several sessions to choose from :");
458 String[] sessions = clientfactory.getCurrentSessions();
459 for (int s = 0; s < sessions.length; s++)
460 System.err.println(sessions[s]);
463 addHandlers(vorbaclient);
465 vorbaclient.joinSession();
466 } catch (Exception se) {
467 se.printStackTrace();
468 System.err.println(se + " when joining session.\n" + Usage);
471 // register an update listener and a close listener.
472 // import any data if requested to
473 if (importFile != null) {
474 File vfile = new File(importFile);
476 vorbaclient.importDocument(vfile);
477 } catch (Exception e) {
478 System.err.println("Failed to import file " + importFile);
479 System.err.println("Exception received was " + e);
480 e.printStackTrace(System.err);
484 // Write out any data if requested to
485 if (outputFile != null) {
486 File vfile = new File(outputFile);
488 vorbaclient.storeDocument(vfile);
489 } catch (Exception e) {
490 System.err.println("Failed to export session as file " + outputFile);
491 System.err.println("Exception received was " + e);
492 e.printStackTrace(System.err);
497 IClientDocument cdoc = vorbaclient.getClientDocument();
498 processVamsasDocument(cdoc);
499 } catch (Exception e) {
501 .println("Unexpected exception when retrieving the client document for the first time!");
502 e.printStackTrace(System.err);
506 ExamplePicker picker = new ExamplePicker(vorbaclient.getClientHandle()
507 .getClientUrn(), vorbaclient.getPickManager());
510 if (picker.pm != null) {
511 picker.pm.registerMessageHandler(new IMessageHandler() {
513 public void handleMessage(Message message) {
514 System.out.println("Received |" + message.getRawMessage() + "|");
515 shutdown += 100; // hang around for 5 seconds or so before dying
522 shutdown = System.currentTimeMillis() + 10000; // hang around for 10
523 // seconds or so before
525 while (!isShuttingdown && update < totalUpdates) {
526 // do something with data
527 // , update document, or something.
530 System.out.println("Update handler called " + (++update) + " times");
531 System.out.println("******************************************");
532 isUpdated = false; // TODO: saner update det method.
533 shutdown = System.currentTimeMillis() + 10000;
534 if (update % 2 == 1) {
536 IClientDocument cdoc = vorbaclient.getClientDocument();
537 processVamsasDocument(cdoc);
538 } catch (Exception e) {
540 .println("Error when updating document after an even numbered update.");
541 e.printStackTrace(System.err);
545 if (System.currentTimeMillis() > shutdown) {
546 isShuttingdown = true;
552 } catch (Exception e) {
556 System.out.println("Finalizing.");
557 // call finalizeClient
558 vorbaclient.finalizeClient();
559 System.out.println("Shutting down picker.");
561 while (picker.isAlive()) {
562 System.out.println("Waiting for picker to die...");
565 } catch (Exception e) {
570 // { meanwhile, eventHandlers are called to do any saves if need be }
571 // and all registered listeners will be deregistered to avoid deadlock.
576 System.out.println("Byee!");
577 //try { Thread.sleep(100000); } catch (Exception e) {}
580 public static void main(String[] args) {
581 ExampleApplication example = new ExampleApplication();