flags for reading/writing client or user appdata only.
[vamsas.git] / src / uk / ac / vamsas / test / ExampleApplication.java
index 328495b..df95ec8 100644 (file)
@@ -1,9 +1,3 @@
-/**
- * Created on 14-Sep-2005
- *
- * TODO To change the template for this generated file go to
- * Window - Preferences - Java - Code Style - Code Templates
- */
 package uk.ac.vamsas.test;
 
 import uk.ac.vamsas.client.*;
@@ -16,134 +10,438 @@ import uk.ac.vamsas.test.objects.Core;
 import java.awt.Event;
 import java.beans.PropertyChangeEvent;
 import java.beans.PropertyChangeListener;
+import java.io.DataInput;
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
 import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
 import java.util.Vector;
+
 /**
- * Toy vamsas command line client application demonstrating the API.
+ * Toy vamsas command line client application demonstrating the API. Currently
+ * runs with one argument: ExampleApplication.main(new String("watch")) Test:
+ * Start up at least two of these processes independently and they will
+ * successively modify and handle update events from the document model.
+ * 
+ * Behaviour of each client: Event handlers are registered for documentUpdate. -
+ * every document update: * the vamsas document will be dumped to standard out
+ * using uk.ac.vamsas.test.simpleclient.ArchiveReports * 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. 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). A new vamsas root generated
+ * from uk.ac.vamsas.test.objects.Core.getDemoVamsas is added to the document.
+ * Then a while loop waits around for events until shutdown: - currently it will
+ * shutdown after 9 updates (totalUpdates) - an update will be made after every
+ * other update that is detected.
+ * 
+ * Status: PickManager now shuts down correctly. Serial updates for two
+ * instances work correctly and are detected under j1.4 (need to test in 1.5 and
+ * 1.6).
+ * 
  * TODO: test appData get/set methods
- * TODO: verify and test pickManager and interaction between it and other session events
- * TODO: add more session interaction events (currently: modifies document on start up, then modifies every 2 updates before finalizing after 5 updates.
+ * 
+ * TODO: verify and test pickManager and interaction between it and other
+ * session events
+ * 
+ * TODO: add more session interaction events
+ * 
+ * TODO: test client add/leave events - currently library generates exceptions
+ * for sessionlist and clientlist modifications.
+ * 
  * @author jimp
  */
 
 public class ExampleApplication {
-  private static ClientHandle app;
-  private static UserHandle user; // TODO: make this something defined by the api
-  private static IClientFactory clientfactory;
-  private static IClient vorbaclient;
-  private static byte[] mydata;
-  private static Vector vamsasObjects;
-  private static boolean isUpdated = false;
-  private static boolean isShuttingdown = false;
-  private static boolean isFinalizing = false;
-  private static void processVamsasDocument(IClientDocument doc) {
-    doc.addVamsasRoot(Core.getDemoVamsas());
-    vorbaclient.updateDocument(doc);
-    // merge vamsasObjects with vamsas objects in document
+  private ClientHandle app;
+
+  private UserHandle user; // TODO: make this something defined by the
+
+  // api
+
+  private IClientFactory clientfactory;
+
+  private IClient vorbaclient;
+
+  private byte[] mydata;
+
+  private Vector vamsasObjects;
+
+  private boolean isUpdated = false;
+
+  private boolean isShuttingdown = false;
+
+  private boolean isFinalizing = false;
+
+  private int totalUpdates = 9;
+
+  private uk.ac.vamsas.client.VorbaId recover = null;
+
+  private int calls = 0;
+
+  private long mdatahash = 0;
+
+  private long muserdatahash = 0;
+
+  private void processVamsasDocument(IClientDocument doc) {
+    if (doc.getVamsasRoots().length < 4) {
+      doc.addVamsasRoot(Core.getDemoVamsas());
+    } else {
+      try {
+        uk.ac.vamsas.objects.core.DataSet ds = doc.getVamsasRoots()[1]
+            .getDataSet(0);
+        uk.ac.vamsas.objects.core.AlignmentSequence alsq = ds.getAlignment(0)
+            .getAlignmentSequence(0);
+        if (recover == null) {
+          recover = alsq.getVorbaId();
+        } else {
+          Vobject recoverd = doc.getObject(recover);
+          System.out.println("Recovery of " + recover + " was "
+              + ((recoverd == null) ? "A FAILURE" : "SUCCESSFUL"));
+        }
+        System.out.println("Modifying Sequence:\n" + alsq.hashCode());
+        alsq.setSequence(alsq.getSequence() + ds.getAlignment(0).getGapChar());
+        System.out.println("Modifying Sequence:\n" + alsq.hashCode());
+        System.out.println("Modified Sequence:\n" + alsq.getSequence());
+        doc.setVamsasRoots(doc.getVamsasRoots());
+      } catch (Exception ee) {
+
+      }
+    }
     // get this apps 'mydata' if it hasn't got it already.
+    System.out.println("Trying to get appdata and modify it.....");
+    try {
+      processAppData(doc);
+      System.out.println(".....Finished.");
+    } catch (Exception e) {
+      System.err.println("Failed to process appdata for our application.");
+      e.printStackTrace(System.err);
+    }
+
     // .. access this application's 'public' mydata' if there is any.
+    vorbaclient.updateDocument(doc);
+    // merge vamsasObjects with vamsas objects in document
+
+  }
+
+  private int appdatareads = 0;
+
+  boolean clientappd = true;
+
+  boolean userappd = false;
+
+  private void processAppData(IClientDocument doc) throws Exception {
+    appdatareads++;
+    boolean writtenonce = false;
+    if (doc != null) {
+      uk.ac.vamsas.client.IClientAppdata appd = doc.getClientAppdata();
+      if (clientappd) {
+        if (appd.hasClientAppdata() && !(appdatareads % 2 == 0)) {
+          // byte[] cappd = appd.getClientAppdata();
+          // if (cappd!=null)
+          // System.out.println("Client appdata\n"+cappd.toString()+"\nEnd of
+          // Appdata\n");
+          System.out.println("Testing read from inputstream");
+          String cappds = readData(appd.getClientInputStream());
+          System.out
+              .println("Client appdata\n" + cappds + "\nEnd of Appdata\n");
+        } else {
+          if (!writtenonce) {
+            String newapd = "Client Appdata:";
+            if (appd.hasClientAppdata()) {
+              AppDataInputStream is;
+              newapd = readData(is = appd.getClientInputStream());
+              is.close();
+            }
+            writtenonce = true;
+            // appd.setClientAppdata(makeappData("Client Appdata for
+            // "+user.toString()+" written"));
+            writeData(appd.getClientOutputStream(), newapd
+                + " : Client Appdata for all users written on " + appdatareads
+                + " read by " + vorbaclient.getUserHandle());
+            System.out.println("Written to ClientAppdata stream.");
+          }
+        }
+      }
+      if (userappd) {
+        if (appd.hasUserAppdata() && !(appdatareads % 2 == 0)) {
+          byte[] cappd = appd.getUserAppdata();
+          if (cappd != null)
+            System.out.println("User appdata\n" + new String(cappd)
+                + "\nEnd of Users' Appdata\n");
+          else {
+            System.out.println("No user appdata.");
+            appd
+                .setUserAppdata(("no default - overwritten null byte set on "
+                    + appdatareads + " read by " + vorbaclient.getUserHandle() + "")
+                    .getBytes());
+          }
+        } else if (!writtenonce) {
+          writtenonce = true;
+          byte[] bts = makeappData("User Appdata for " + user + " written on "
+              + appdatareads + " read at ");
+          System.out.println("Setting appData bytes to\n" + new String(bts)
+              + "\nEnd.");
+          appd.setUserAppdata(bts);
+          System.out.println("Written to UserAppdata stream.");
+        }
+      }
+    }
   }
-  private static void addHandlers(IClient avorbaclient) {
+
+  private byte[] makeappData(String message) {
+    StringBuffer sb = new StringBuffer();
+    sb.append(message);
+    sb.append("on " + new java.util.Date());
+    return sb.toString().getBytes();
+  }
+
+  private boolean writeData(AppDataOutputStream os, String message) {
+    StringBuffer sb = new StringBuffer();
+    sb.append(message);
+    sb.append("on " + new java.util.Date());
+    try {
+      ObjectOutputStream oos = new ObjectOutputStream(os);
+      oos.writeObject(sb.toString());
+      oos.flush();
+      oos.close();
+    } catch (Exception e) {
+      System.err.println("Problem serialising this message:\n" + sb);
+      e.printStackTrace(System.err);
+      return false;
+    }
+    return true;
+  }
+
+  private String readData(AppDataInputStream is) {
+    if (is != null) {
+      try {
+        if (is.available() > 0) {
+          ObjectInputStream ois = new ObjectInputStream(is);
+          String rs = (String) ois.readObject();
+          return rs;
+        }
+      } catch (Exception e) {
+        System.err.println("Failed to read a string from input stream!");
+        e.printStackTrace(System.err);
+      }
+    }
+    return "";
+  }
+
+  private void addHandlers(IClient avorbaclient) {
+    final ExampleApplication me = this;
     // make a non-volatile reference to the client instance.
     final IClient vorbaclient = avorbaclient;
     // register update handler
     vorbaclient.addDocumentUpdateHandler(new PropertyChangeListener() {
       public void propertyChange(PropertyChangeEvent evt) {
-        System.out.println("Vamsas document update for "+evt.getPropertyName()
-            +": "+evt.getOldValue()+" to "+evt.getNewValue());
+        System.out.println("Vamsas document update for "
+            + evt.getPropertyName() + ": " + evt.getOldValue() + " to "
+            + evt.getNewValue());
         // merge new data into ours.
         // example - output doc
         try {
           IClientDocument cdoc = vorbaclient.getClientDocument();
-          uk.ac.vamsas.test.simpleclient.ArchiveReports.rootReport(cdoc.getVamsasRoots(), true, System.out);
+          if (calls > 2 && cdoc.getVamsasRoots().length > 0
+              && !cdoc.getVamsasRoots()[0].is__stored_in_document()) {
+            System.err
+                .println("Pathological Update Detected - Document is zeroed!");
+          }
+          calls++;
+          uk.ac.vamsas.test.simpleclient.ArchiveReports.rootReport(cdoc
+              .getVamsasRoots(), true, System.out);
+          // Simple update
+          try {
+            if (cdoc.getVamsasRoots().length > 2) {
+              uk.ac.vamsas.objects.core.DataSet ds = cdoc.getVamsasRoots()[1]
+                  .getDataSet(0);
+              uk.ac.vamsas.objects.core.AlignmentSequence alsq = ds
+                  .getAlignment(0).getAlignmentSequence(0);
+              if (alsq.isUpdated())
+                System.out.println("Seqeuence was updated since last time.");
+              alsq.setSequence(alsq.getSequence()
+                  + ds.getAlignment(0).getGapChar());
+              System.out.println("Newly Modified Sequence:\n"
+                  + alsq.getSequence());
+              cdoc.setVamsasRoots(cdoc.getVamsasRoots());
+            }
+          } catch (Exception ee) {
+            System.err.println("Exception whilst updating :");
+            ee.printStackTrace(System.err);
+          }
           vorbaclient.updateDocument(cdoc);
         } catch (Exception e) {
-          System.err.println("Exception whilst dumping document tree after an update.");
+          System.err
+              .println("Exception whilst dumping document tree after an update.");
           e.printStackTrace(System.err);
         }
-        isUpdated=true; // tell main thread to reflect change...
+        isUpdated = true; // tell main thread to reflect change...
       }
     });
     // register close handler
-    vorbaclient.addVorbaEventHandler(Events.DOCUMENT_REQUESTTOCLOSE, 
+    vorbaclient.addVorbaEventHandler(Events.DOCUMENT_REQUESTTOCLOSE,
         new PropertyChangeListener() {
-       public void propertyChange(PropertyChangeEvent evt) {
-         System.out.println("Received request to close vamsas document.");
-         // ask user for a filename to save it to. 
-         // Then pass it to the vorba object...
-         vorbaclient.storeDocument(new java.io.File("UserLocation"));
-       }
-    });
-    
+          public void propertyChange(PropertyChangeEvent evt) {
+            System.out.println("Received request to close vamsas document.");
+            // ask user for a filename to save it to.
+            // Then pass it to the vorba object...
+            vorbaclient.storeDocument(new java.io.File("UserLocation"));
+          }
+        });
+
     // register some more handlers to monitor the session :
-    
-    vorbaclient.addVorbaEventHandler(Events.CLIENT_CREATION, 
+
+    vorbaclient.addVorbaEventHandler(Events.CLIENT_CREATION,
         new PropertyChangeListener() {
-      public void propertyChange(PropertyChangeEvent evt) {
-        System.out.println("New Vamsas client for "+evt.getPropertyName()
-            +": "+evt.getOldValue()+" to "+evt.getNewValue());
-        // tell app add new client to its list of clients.
-      }
-    });
-    vorbaclient.addVorbaEventHandler(Events.CLIENT_FINALIZATION, 
+          public void propertyChange(PropertyChangeEvent evt) {
+            System.out.println("New Vamsas client for " + evt.getPropertyName()
+                + ": " + evt.getOldValue() + " to " + evt.getNewValue());
+            // tell app add new client to its list of clients.
+          }
+        });
+    vorbaclient.addVorbaEventHandler(Events.CLIENT_FINALIZATION,
         new PropertyChangeListener() {
-      public void propertyChange(PropertyChangeEvent evt) {
-        System.out.println("Vamsas client finalizing for "+evt.getPropertyName()
-            +": "+evt.getOldValue()+" to "+evt.getNewValue());
-        // tell app to update its list of clients to communicate with.
-      }
-    });
-    vorbaclient.addVorbaEventHandler(Events.SESSION_SHUTDOWN, 
+          public void propertyChange(PropertyChangeEvent evt) {
+            System.out.println("Vamsas client finalizing for "
+                + evt.getPropertyName() + ": " + evt.getOldValue() + " to "
+                + evt.getNewValue());
+            // tell app to update its list of clients to communicate
+            // with.
+          }
+        });
+    vorbaclient.addVorbaEventHandler(Events.SESSION_SHUTDOWN,
         new PropertyChangeListener() {
-      public void propertyChange(PropertyChangeEvent evt) {
-        System.out.println("Session "+evt.getPropertyName()+" is shutting down.");
-        // tell app to finalize its session data before shutdown.
-      }
-    });
-    vorbaclient.addVorbaEventHandler(Events.DOCUMENT_FINALIZEAPPDATA, 
+          public void propertyChange(PropertyChangeEvent evt) {
+            System.out.println("Session " + evt.getPropertyName()
+                + " is shutting down.");
+            // tell app to finalize its session data before
+            // shutdown.
+          }
+        });
+    vorbaclient.addVorbaEventHandler(Events.DOCUMENT_FINALIZEAPPDATA,
         new PropertyChangeListener() {
-      public void propertyChange(PropertyChangeEvent evt) {
-        System.out.println("Application received a DOCUMENT_FINALIZEAPPDATA event.");
-        // tell app to finalize its session data prior to the storage of the current session as an archive.
-      }
-    });
-    
+          public void propertyChange(PropertyChangeEvent evt) {
+            boolean finalized = false;
+            System.out
+                .println("Application received a DOCUMENT_FINALIZEAPPDATA event.");
+            IClientDocument cdoc = null;
+            try {
+              cdoc = vorbaclient.getClientDocument();
+              if (cdoc != null) {
+                IClientAppdata apd = cdoc.getClientAppdata();
+                if (apd != null) {
+                  String userd = "";
+                  if (apd.getUserAppdata() != null) {
+                    userd = new String(apd.getUserAppdata());
+                  }
+                  String appdat = me.readData(apd.getClientInputStream());
+                  me.writeData(apd.getClientOutputStream(), appdat
+                      + "\nUser Data merged\n" + userd + "\n");
+                }
+                finalized = true;
+                vorbaclient.updateDocument(cdoc);
+              }
+              // tell app to finalize its session data prior to the
+              // storage of the current session as an archive.
+            } catch (Exception e) {
+              if (!finalized) {
+                System.err
+                    .println("Probable library problem - exception when trying to update document after writing merged appdata.");
+                e.printStackTrace(System.err);
+              } else {
+                System.err
+                    .println("Recovering from exception when writing merged appdata");
+                e.printStackTrace(System.err);
+                try {
+                  if (cdoc != null) {
+                    vorbaclient.updateDocument(cdoc);
+                  }
+                } catch (Exception e2) {
+                  System.err
+                      .println("Probable library problem - exception when trying to update document after an exception when writing merged appdata.");
+                  e2.printStackTrace(System.err);
+                }
+              }
+              return;
+            }
+            System.out.println("Application finalized appdata successfuly.");
+          }
+
+        });
   }
-  public static String 
-       Usage="ExampleApplication [session urn] watch/n( future usage is :/n <vamsasFileDirectory> <vamsasSessionURN> <action> [+<arguments>]\n"
-         +"<action> is one of :\n\tsave,update,close,watch";
-  static String sess=null;
-  private static boolean parseArgs(String args[]) {
-    if (args.length==0) {
+
+  public String Usage = "ExampleApplication :/n [-arena <vamsasFileDirectory>][-session <vamsasSessionURN>] <action> [+<arguments>]\n"
+      + "<action> is one of :\n\tsave,update,close,watch";
+
+  String sess = null;
+
+  String importFile = null;
+
+  String outputFile = null;
+
+  private boolean parseArgs(String args[]) {
+    if (args.length == 0) {
       return false;
     }
-    if (!args[0].toLowerCase().equals("watch")) {
-      sess=args[0];
+    int cpos = 0;
+    boolean parsed = false;
+    while (!parsed && cpos < args.length) {
+      if (args[cpos].toLowerCase().equals("load") && cpos + 1 < args.length) {
+        importFile = args[cpos + 1];
+        cpos += 2;
+        continue;
+      }
+      if (args[cpos].toLowerCase().equals("save") && cpos + 1 < args.length) {
+        outputFile = args[cpos + 1];
+        cpos += 2;
+        continue;
+      }
+      // default behaviour - if not anything else its probably a session urn
+      if (!args[cpos].toLowerCase().equals("watch")) {
+        sess = args[cpos];
+      }
+      cpos++;
     }
     return true;
   }
-  public static void main(String[] args) {
-    class ExamplePicker implements Runnable {
-      String me=null;
-      public IPickManager pm = null;
-      ExamplePicker(String me,IPickManager pm) {
-        this.me = me;
-        this.pm = pm;
-      }
-      public void run() {
-        int mcount=1;
-        while (pm!=null) {
-          try { Thread.sleep(1000+(long) Math.random()*10000); }
-          catch (Exception e){ };
-          if (pm!=null)
-          {
-            pm.sendMessage(new uk.ac.vamsas.client.picking.CustomMessage("Message "+mcount+++" from "+me));
-          }
+
+  class ExamplePicker extends Thread {
+    String me = null;
+
+    public IPickManager pm = null;
+
+    ExamplePicker(String me, IPickManager pm) {
+      this.me = me;
+      this.pm = pm;
+    }
+
+    public void run() {
+      int mcount = 1;
+      while (pm != null) {
+        try {
+          Thread.sleep(1000 + (long) Math.random() * 10000);
+        } catch (Exception e) {
+        }
+
+        if (pm != null) {
+          pm.sendMessage(new uk.ac.vamsas.client.picking.CustomMessage(
+              "Message " + mcount++ + " from " + me));
         }
       }
-        
-    };
+    }
 
+  }
+
+  long shutdown = -1;
+
+  public void runMe(String[] args) {
     if (!parseArgs(args)) {
       System.err.print(Usage);
     }
@@ -151,88 +449,150 @@ public class ExampleApplication {
     try {
       clientfactory = new uk.ac.vamsas.client.simpleclient.SimpleClientFactory();
     } catch (IOException e) {
-      System.err.println(e+"\n"+Usage);
+      System.err.println(e + "\n" + Usage);
       System.exit(1);
     }
-    
+
     // get an Iclient with session data
-    app = new ClientHandle("uk.ac.vamsas.test.ExampleApplication","0.1");
-    user = new UserHandle("arnolduser","deathsdoor");
+    app = new ClientHandle("uk.ac.vamsas.test.ExampleApplication", "0.1");
+    user = new UserHandle("arnolduser", "deathsdoor");
     try {
-      vorbaclient = clientfactory.getIClient(app, user);
+      if (sess != null) {
+        System.out.println("Connecting to " + sess);
+        vorbaclient = clientfactory.getIClient(app, user, sess);
+      } else {
+        vorbaclient = clientfactory.getIClient(app, user);
+      }
     } catch (NoDefaultSessionException e) {
-      System.err.println("There appear to be several sessions to choose from :");
+      System.err
+          .println("There appear to be several sessions to choose from :");
       String[] sessions = clientfactory.getCurrentSessions();
-      for (int s=0;s<sessions.length; s++)
+      for (int s = 0; s < sessions.length; s++)
         System.err.println(sessions[s]);
       System.exit(2);
     }
     addHandlers(vorbaclient);
     try {
       vorbaclient.joinSession();
-    }
-    catch (Exception se) {
+    } catch (Exception se) {
       se.printStackTrace();
-      System.err.println(se+" when joining session.\n"+Usage);
+      System.err.println(se + " when joining session.\n" + Usage);
       System.exit(1);
     }
     // register an update listener and a close listener.
+    // import any data if requested to
+    if (importFile != null) {
+      File vfile = new File(importFile);
+      try {
+        vorbaclient.importDocument(vfile);
+      } catch (Exception e) {
+        System.err.println("Failed to import file " + importFile);
+        System.err.println("Exception received was " + e);
+        e.printStackTrace(System.err);
+      }
+
+    }
+    // Write out any data if requested to
+    if (outputFile != null) {
+      File vfile = new File(outputFile);
+      try {
+        vorbaclient.storeDocument(vfile);
+      } catch (Exception e) {
+        System.err.println("Failed to export session as file " + outputFile);
+        System.err.println("Exception received was " + e);
+        e.printStackTrace(System.err);
+      }
+    }
     // get document data
     try {
       IClientDocument cdoc = vorbaclient.getClientDocument();
       processVamsasDocument(cdoc);
     } catch (Exception e) {
-      System.err.println("Unexpected exception when retrieving the client document for the first time!");
+      System.err
+          .println("Unexpected exception when retrieving the client document for the first time!");
       e.printStackTrace(System.err);
       System.exit(1);
     }
-    int update=0;
-    ExamplePicker picker = new ExamplePicker(vorbaclient.getClientHandle().getClientUrn(),vorbaclient.getPickManager());
-    Thread pickthread = new Thread(picker);
-    pickthread.start();
-    picker.pm.registerMessageHandler(new IMessageHandler() {
+    int update = 0;
+    ExamplePicker picker = new ExamplePicker(vorbaclient.getClientHandle()
+        .getClientUrn(), vorbaclient.getPickManager());
 
-      public void handleMessage(Message message) {
-        System.out.println("Received |"+message.getRawMessage()+"|");
-      }
-      
-    });
-    while (!isShuttingdown && update<5) {
+    picker.start();
+    if (picker.pm != null) {
+      picker.pm.registerMessageHandler(new IMessageHandler() {
+
+        public void handleMessage(Message message) {
+          System.out.println("Received |" + message.getRawMessage() + "|");
+          shutdown += 100; // hang around for 5 seconds or so before dying
+          // naturally.
+
+        }
+
+      });
+    }
+    shutdown = System.currentTimeMillis() + 10000; // hang around for 10
+    // seconds or so before
+    // dying naturally.
+    while (!isShuttingdown && update < totalUpdates) {
       // do something with data
       // , update document, or something.
       // ..
       if (isUpdated) {
-        System.out.println("Update handler called "+(++update)+" times");
+        System.out.println("Update handler called " + (++update) + " times");
         System.out.println("******************************************");
-        isUpdated=false; // TODO: saner update det method.
-        if (update % 2==1) {
+        isUpdated = false; // TODO: saner update det method.
+        shutdown = System.currentTimeMillis() + 10000;
+        if (update % 2 == 1) {
           try {
             IClientDocument cdoc = vorbaclient.getClientDocument();
             processVamsasDocument(cdoc);
-          }
-          catch (Exception e) {
-            System.err.println("Error when updating document after an even numbered update.");
+          } catch (Exception e) {
+            System.err
+                .println("Error when updating document after an even numbered update.");
             e.printStackTrace(System.err);
           }
+          try {
+            Thread.sleep(200);
+          } catch (Exception e){}
+        }
+      } else {
+        if (System.currentTimeMillis() > shutdown) {
+          isShuttingdown = true;
         }
       }
-      try { Thread.sleep(15); } catch (Exception e) {};
+
+      try {
+        Thread.sleep(50);
+      } catch (Exception e) {
+      }
+
     }
+    System.out.println("Finalizing.");
+    // call finalizeClient
+    vorbaclient.finalizeClient();
     System.out.println("Shutting down picker.");
-    picker.pm=null;
-    while (pickthread.isAlive()) {
+    picker.pm = null;
+    while (picker.isAlive()) {
       System.out.println("Waiting for picker to die...");
-      try { Thread.sleep(1000); 
-      } catch (Exception e) {};
+      try {
+        Thread.sleep(1000);
+      } catch (Exception e) {
+      }
+      ;
     }
-  
-    System.out.println("Finalizing.");
-      // call finalizeClient
-    vorbaclient.finalizeClient();
+
     // { meanwhile, eventHandlers are called to do any saves if need be }
     // and all registered listeners will be deregistered to avoid deadlock.
-    
+
     // finish
+    vorbaclient = null;
+    clientfactory = null;
+    System.out.println("Byee!");
+    // try { Thread.sleep(100000); } catch (Exception e) {}
+  }
+
+  public static void main(String[] args) {
+    ExampleApplication example = new ExampleApplication();
+    example.runMe(args);
   }
-  
 }