Removed clientfile watcher elements in attempt to remove any locks after client is...
authorjprocter <jprocter@compbio.dundee.ac.uk>
Wed, 22 Aug 2007 16:15:06 +0000 (16:15 +0000)
committerjprocter <jprocter@compbio.dundee.ac.uk>
Wed, 22 Aug 2007 16:15:06 +0000 (16:15 +0000)
git-svn-id: https://svn.lifesci.dundee.ac.uk/svn/repository/trunk@444 be28352e-c001-0410-b1a7-c7978e42abec

src/uk/ac/vamsas/client/simpleclient/VamsasSession.java

index 2ae181d..45766d4 100644 (file)
@@ -18,6 +18,7 @@ import uk.ac.vamsas.client.Events;
 import uk.ac.vamsas.client.IClient;
 import uk.ac.vamsas.client.SessionHandle;
 import uk.ac.vamsas.client.UserHandle;
+
 /**
  * Does all the IO operations for a SimpleClient instance accessing 
  * a SimpleClient vamsas session.
@@ -75,59 +76,71 @@ public class VamsasSession {
    * they should finalise their vamsas datasets for 
    * storing into a vamsas archive.
    */
-  public static final String CLOSEANDSAVE_FILE="stored.log";
+  public static final String CLOSEANDSAVE_FILE = "stored.log";
+
   /**
    * session file storing the last_stored_stat data 
    */
-  public static final String MODIFIEDDOC_FILE="modified";
+  public static final String MODIFIEDDOC_FILE = "modified";
 
-  
   private SimpleSessionManager sessionManager = null;
-  
+
   /**
    * Count of cycles before considering the current client as the last one of the session (if no other client registered as active )
    */
-  private final int watchCycleCountBeforeLastClient = 1220 ;
-  
+  private final int watchCycleCountBeforeLastClient = 1220;
+
   /**
    * time between checking 
    */
-  public int WATCH_SLEEP=30; 
-  
+  public int WATCH_SLEEP = 30;
+
   protected String clientFileDirectory = "clients";
-  
+
   /**
    * called to clear update flag after a successful offline storage event
    */
   protected void clearUnsavedFlag() {
-    SessionFlagFile laststored = new SessionFlagFile(new File(sessionDir, MODIFIEDDOC_FILE));
+    SessionFlagFile laststored = new SessionFlagFile(new File(sessionDir,
+        MODIFIEDDOC_FILE));
     if (!laststored.clearFlag())
-      log.warn("Unsaved flag was not cleared for "+sessionDir);
+      log.warn("Unsaved flag was not cleared for " + sessionDir);
   }
+
   /**
    * called to indicate session document has been modified.
    *
    */
   protected void setUnsavedFlag() {
-    SessionFlagFile laststored = new SessionFlagFile(new File(sessionDir, MODIFIEDDOC_FILE));
+    SessionFlagFile laststored = new SessionFlagFile(new File(sessionDir,
+        MODIFIEDDOC_FILE));
     if (!laststored.setFlag())
-      log.warn("Couldn't set the Unsaved flag for "+sessionDir);
+      log.warn("Couldn't set the Unsaved flag for " + sessionDir);
   }
+
   /**
    * 
    * @return true if session document has been modified since last offline storage event 
    */
   protected boolean getUnsavedFlag() {
-    SessionFlagFile laststored = new SessionFlagFile(new File(sessionDir, MODIFIEDDOC_FILE));
+    SessionFlagFile laststored = new SessionFlagFile(new File(sessionDir,
+        MODIFIEDDOC_FILE));
     return laststored.checkFlag();
   }
+
   /**
    * log file location
    */
-  public static final String SESSION_LOG="Log.txt";
+  public static final String SESSION_LOG = "Log.txt";
+
   private static Log log = LogFactory.getLog(VamsasSession.class);
+
   protected Logger slog = Logger.getLogger("uk.ac.vamsas.client.SessionLog");
   /**
+   * the appender that writes to the log file inside the session's directory.
+   */
+  private FileAppender slogAppender=null;
+  /**
    * setup the sessionLog using Log4j.
    * @throws IOException
    */
@@ -141,102 +154,130 @@ public class VamsasSession {
       System.out.println(e.nextElement());
 
     }*/
-  
-    if (slog!= null ) {
-      File sessionLogFile =  new File(this.sessionDir, SESSION_LOG);
-      slog.addAppender(new FileAppender(new PatternLayout("%-4r [%t] %-5p %c %x - %m%n"), sessionLogFile.getAbsolutePath(), true));
+
+    if (slog != null) {
+      File sessionLogFile = new File(this.sessionDir, SESSION_LOG);
+      slog.addAppender(slogAppender = new FileAppender(new PatternLayout(
+          "%-4r [%t] %-5p %c %x - %m%n"), sessionLogFile.getAbsolutePath(),
+          true));
     } else {
       log.info("No appender for SessionLog");
     }
   }
-  
+  private void closeSessionLog() {
+    if (slog!=null)
+    {
+      if (slogAppender!=null)
+      {
+        slog.removeAppender(slogAppender);
+        slogAppender.close();
+        slogAppender = null;
+      }
+    }
+  }
+
   /**
    * the sessionDir is given as the session location for new clients.
    */
   protected File sessionDir;
+
   /**
    * holds the list of attached clients
    */
   ClientsFile clist;
-  public static final String CLIENT_LIST="Clients.obj";
+
+  public static final String CLIENT_LIST = "Clients.obj";
+
   /**
    * holds the data
    */
-  VamsasFile vamArchive; 
-  public static final String VAMSAS_OBJ="VamDoc.jar";
-  
+  VamsasFile vamArchive;
+
+  public static final String VAMSAS_OBJ = "VamDoc.jar";
+
   /**
    * sets up the vamsas session files and watchers in sessionDir
    * @param sessionDir1
    */
   protected VamsasSession(File sessionDir1) throws IOException {
-    if (sessionDir1==null)
+    if (sessionDir1 == null)
       throw new Error("Null directory for VamsasSession.");
     if (sessionDir1.exists()) {
-      if (!sessionDir1.isDirectory() || !sessionDir1.canWrite() || !sessionDir1.canRead())
-        throw new IOException("Cannot access '"+sessionDir1+"' as a read/writable Directory.");
+      if (!sessionDir1.isDirectory() || !sessionDir1.canWrite()
+          || !sessionDir1.canRead())
+        throw new IOException("Cannot access '" + sessionDir1
+            + "' as a read/writable Directory.");
       if (!checkSessionFiles(sessionDir1))
-      log.warn("checkSessionFiles() returned false. Possible client implementation error");
-      this.sessionDir = sessionDir1; 
+        log
+            .warn("checkSessionFiles() returned false. Possible client implementation error");
+      this.sessionDir = sessionDir1;
       initSessionObjects();
       slog.debug("Initialising additional VamsasSession instance");
-      log.debug("Attached to VamsasSession in "+sessionDir1);
+      log.debug("Attached to VamsasSession in " + sessionDir1);
       //} 
     } else {
       // start from scratch
       if (!sessionDir1.mkdir())
-        throw new IOException("Failed to make VamsasSession directory in "+sessionDir1);
+        throw new IOException("Failed to make VamsasSession directory in "
+            + sessionDir1);
       createSessionFiles();
       initSessionObjects();
       slog.debug("Session directory created.");
-      log.debug("Initialised VamsasSession in "+sessionDir1);
+      log.debug("Initialised VamsasSession in " + sessionDir1);
     }
   }
+
   /**
    * tests presence of existing sessionfiles files in dir
    * @param dir
    * @return
    */
   private boolean checkSessionFiles(File dir) throws IOException {
-    File c_file = new File(dir,CLIENT_LIST);
-    File v_doc = new File(dir,VAMSAS_OBJ);
+    File c_file = new File(dir, CLIENT_LIST);
+    File v_doc = new File(dir, VAMSAS_OBJ);
     if (c_file.exists() && v_doc.exists())
       return true;
     return false;
   }
+
   /**
    * create new empty files in dir
    *
    */
   private void createSessionFiles() throws IOException {
-    if (sessionDir==null)
-      throw new IOException("Invalid call to createSessionFiles() with null sessionDir");
-    File c_file = new File(sessionDir,CLIENT_LIST);
-    File v_doc = new File(sessionDir,VAMSAS_OBJ);
+    if (sessionDir == null)
+      throw new IOException(
+          "Invalid call to createSessionFiles() with null sessionDir");
+    File c_file = new File(sessionDir, CLIENT_LIST);
+    File v_doc = new File(sessionDir, VAMSAS_OBJ);
     if (!c_file.exists() && c_file.createNewFile())
-      log.debug("Created new ClientFile "+c_file); // don't care if this works or not
+      log.debug("Created new ClientFile " + c_file); // don't care if this works or not
     if (!v_doc.exists() && v_doc.createNewFile())
-      log.debug("Created new Vamsas Session Document File "+v_doc); 
+      log.debug("Created new Vamsas Session Document File " + v_doc);
   }
+
   /**
    * construct SessionFile objects and watchers for each
    */
   private void initSessionObjects() throws IOException {
     createSessionFiles();
-    if (clist!=null || vamArchive!=null)
-      throw new IOException("initSessionObjects called for initialised VamsasSession object.");
-    clist = new ClientsFile(new File(sessionDir,CLIENT_LIST));
-    vamArchive = new VamsasFile(new File(sessionDir,VAMSAS_OBJ));
-    storedocfile=new ClientsFile(new File(sessionDir, CLOSEANDSAVE_FILE));
+    if (clist != null || vamArchive != null)
+      throw new IOException(
+          "initSessionObjects called for initialised VamsasSession object.");
+    clist = new ClientsFile(new File(sessionDir, CLIENT_LIST));
+    vamArchive = new VamsasFile(new File(sessionDir, VAMSAS_OBJ));
+    storedocfile = new ClientsFile(new File(sessionDir, CLOSEANDSAVE_FILE));
     initLog();
   }
+
   /**
    * make a new watcher object for the clientFile
    * @return new ClientFile watcher instance
    */
- public FileWatcher getClientWatcher() {
+  public FileWatcher getClientWatcher() {
     return new FileWatcher(clist.sessionFile);
   }
+
   /**
    * make a new watcher object for the vamsas Document
    * @return new ClientFile watcher instance
@@ -244,16 +285,20 @@ public class VamsasSession {
   public FileWatcher getDocWatcher() {
     return new FileWatcher(vamArchive.sessionFile);
   }
-  FileWatcher store_doc_file=null;
-  public ClientsFile storedocfile=null;
+
+  FileWatcher store_doc_file = null;
+
+  public ClientsFile storedocfile = null;
+
   /**
    * make a new watcher object for the messages file
    * @return new watcher instance
    */
   public FileWatcher getStoreWatcher() {
-    return new FileWatcher(new File(sessionDir,CLOSEANDSAVE_FILE));
+    return new FileWatcher(new File(sessionDir, CLOSEANDSAVE_FILE));
 
   }
+
   /**
    * write to the StoreWatcher file to indicate that a storeDocumentRequest has been made.
    * The local client's storeWatcher FileWatcher object is updated so the initial change is not registered.
@@ -261,44 +306,52 @@ public class VamsasSession {
    * @param user
    * @return
    */
-  public void addStoreDocumentRequest(ClientHandle client, UserHandle user) throws IOException {
+  public void addStoreDocumentRequest(ClientHandle client, UserHandle user)
+      throws IOException {
     // TODO: replace this with clientsFile mechanism
     SessionFile sfw = new SessionFile(new File(sessionDir, CLOSEANDSAVE_FILE));
     while (!sfw.lockFile())
-      log.debug("Trying to get lock for "+CLOSEANDSAVE_FILE);
-    RandomAccessFile sfwfile=sfw.fileLock.getRaFile();
+      log.debug("Trying to get lock for " + CLOSEANDSAVE_FILE);
+    RandomAccessFile sfwfile = sfw.fileLock.getRaFile();
     sfwfile.setLength(0); // wipe out any old info.
     // TODO: rationalise what gets written to this file (ie do we want other clients to read the id of the requestor?)
-    sfwfile.writeUTF(client.getClientUrn()+":"+user.getFullName()+"@"+user.getOrganization());
+    sfwfile.writeUTF(client.getClientUrn() + ":" + user.getFullName() + "@"
+        + user.getOrganization());
     sfw.unlockFile();
-    if (store_doc_file!=null)
+    if (store_doc_file != null)
       store_doc_file.setState();
-    slog.info("FinalizeAppData request from "+user.getFullName()+" using "+client.getClientUrn()+"");
+    slog.info("FinalizeAppData request from " + user.getFullName() + " using "
+        + client.getClientUrn() + "");
   }
+
   /**
    * create a new session with an existing vamsas Document - by copying it into the session.
    * @param archive
    */
   public void setVamsasDocument(File archive) throws IOException {
-    log.debug("Transferring vamsas data from "+archive+" to session:"+vamArchive.sessionFile);
+    log.debug("Transferring vamsas data from " + archive + " to session:"
+        + vamArchive.sessionFile);
     SessionFile xtantdoc = new SessionFile(archive);
     vamArchive.updateFrom(null, xtantdoc);
     // LATER: decide if session archive provenance should be updated to reflect access.
     // TODO: soon! do a proper import objects from external file 
     log.debug("Transfer complete.");
   }
+
   /**
    * write session as a new vamsas Document (this will overwrite any existing file without warning)
    * TODO: test
    * TODO: verify that lock should be released for vamsas document.
    * @param destarchive
    */
-  protected void writeVamsasDocument(File destarchive, Lock extlock) throws IOException {
-    log.debug("Transferring vamsas data from "+vamArchive.sessionFile+" to session:"+destarchive);
+  protected void writeVamsasDocument(File destarchive, Lock extlock)
+      throws IOException {
+    log.debug("Transferring vamsas data from " + vamArchive.sessionFile
+        + " to session:" + destarchive);
     SessionFile newdoc = new SessionFile(destarchive);
-    if (extlock==null && !vamArchive.lockFile())
+    if (extlock == null && !vamArchive.lockFile())
       while (!vamArchive.lockFile())
-        log.info("Trying to get lock for "+vamArchive.sessionFile);
+        log.info("Trying to get lock for " + vamArchive.sessionFile);
     // TODO: LATER: decide if a provenance entry should be written in the exported document recording the export from the session
     newdoc.updateFrom(extlock, vamArchive);
     // LATER: LATER: fix use of updateFrom for file systems where locks cannot be made (because they don't have a lockManager, ie NFS/Unix, etc).
@@ -306,10 +359,12 @@ public class VamsasSession {
     newdoc.unlockFile();
     log.debug("Transfer complete.");
   }
+
   /**
-        * extant archive IO handler
-        */
-  VamsasArchive _va=null;
+   * extant archive IO handler
+   */
+  VamsasArchive _va = null;
+
   /**
    * Creates a VamsasArchive Vobject for accessing and updating document
    * Note: this will lock the Vamsas Document for exclusive access to the client.
@@ -318,33 +373,36 @@ public class VamsasSession {
    */
   protected VamsasArchive getVamsasDocument() throws IOException {
     // check we haven't already done this once - probably should be done by caller
-    if (_va!=null)
+    if (_va != null)
       return _va;
     // patiently wait for a lock on the document. (from ArchiveClient.getUpdateable())
-    long tries=5000;
-    while (vamArchive.getLock()==null && --tries>0) {
-//       Thread.sleep(1);
-        log.debug("Trying to get a document lock for the "+tries+"'th time.");
-      }
-    if (tries==0) 
+    long tries = 5000;
+    while (vamArchive.getLock() == null && --tries > 0) {
+      //       Thread.sleep(1);
+      log.debug("Trying to get a document lock for the " + tries + "'th time.");
+    }
+    if (tries == 0)
       throw new IOException("Failed to get lock for vamsas archive.");
-      
-    VamsasArchive va = new VamsasArchive(vamArchive.sessionFile, false, true, vamArchive);
+
+    VamsasArchive va = new VamsasArchive(vamArchive.sessionFile, false, true,
+        vamArchive);
 
     return va;
   }
+
   /**
    * Unlocks the vamsas archive session document after it has been closed.
    * @throws IOException
    */
   protected void unlockVamsasDocument() throws IOException {
-    if (_va!=null)
+    if (_va != null)
       _va.closeArchive();
-    _va=null;
-    if (vamArchive!=null)
+    _va = null;
+    if (vamArchive != null)
       vamArchive.unLock();
-    
+
   }
+
   /**
    * create a uniquely named uk.ac.vamsas.client.simpleclient.ClientsFile.addClient(ClientHandle)ile in the session Directory
    * @see java.io.File.createTempFile
@@ -353,27 +411,27 @@ public class VamsasSession {
    * @return SessionFile object configured for the new file (of length zero)
    * @throws IOException
    */
-  protected SessionFile getTempSessionFile(String pref, String suff) throws IOException {
-    File tfile = File.createTempFile(pref,suff,sessionDir);
+  protected SessionFile getTempSessionFile(String pref, String suff)
+      throws IOException {
+    File tfile = File.createTempFile(pref, suff, sessionDir);
     SessionFile tempFile = new SessionFile(tfile);
     return tempFile;
   }
-  
+
   /**
    * add a IClient to the session
    * 
    * add the client to the client list file
    * @param client client to add to the session
    */
-  protected void addClient(SimpleClient client)
-  {
+  protected void addClient(SimpleClient client) {
     if (client == null)
       slog.error("Try to add a null client to the session ");
     else {
-      log.debug("Adding client "+client.getClientHandle().getClientUrn());
+      log.debug("Adding client " + client.getClientHandle().getClientUrn());
       getClientWatcherElement().haltWatch();
       clist.addClient(client.getClientHandle());
-     
+
       log.debug("Added.");
       log.debug("Register Client as Active.");
       try {
@@ -384,375 +442,369 @@ public class VamsasSession {
       //tracks modification to the client list and readds client to the list
       getClientWatcherElement().setHandler(new AddClientWatchCallBack(client));
       getClientWatcherElement().enableWatch();
-     
+
     }
   }
-  
+
   /**
    * Handler for the client watcher.
    * 
    * If (the current client is not in the client list, it is added again;)
-   */  
-  private class AddClientWatchCallBack  implements WatcherCallBack
-  {
-   
-    private SimpleClient client ;
-    
+   */
+  private class AddClientWatchCallBack implements WatcherCallBack {
+
+    private SimpleClient client;
+
     /**
-    *Inits the handler with the client to check in the list
+     *Inits the handler with the client to check in the list
      * @param client client to monitor in the client list
      */
-    protected  AddClientWatchCallBack (SimpleClient client)
-      {
-        this.client = client;
-      }
-    
-      /**
-       * If the client list is modified, checks if the current is still in the list. otherwise, readds ti.
-       * @return true to enable watcher, or false to disable it in future WatcherThread cycles.
-       */
-      public boolean handleWatchEvent(WatcherElement watcher, Lock lock)
-        {
-          boolean isWatchEnable = watcher.isWatchEnabled();
-          if (lock== null)//no update on the list
-            return isWatchEnable;
-          log.debug("change on the client list ");
-          if (client != null)
-            {
-        
-            
-            //checks if the client is not already in the lists
-              ClientHandle[] cl = clist.retrieveClientList(lock);//clist.retrieveClientList();
-              boolean found = false;
-              if (cl != null)
-                {
-                  for (int chi = cl.length-1; !found && chi > -1; chi--) {
-                    found =  cl[chi].equals(this.client.getClientHandle());
-                  }
-                 
-                } 
-              if (! found) 
-                {log.debug("client not in the list ");
-                  if( log.isDebugEnabled())
-                      log.debug("the client has not been found in the list. Adding it again :"+cl);
-                    addClient(client);
-              }
-              else
-                log.debug("client is in the list");
+    protected AddClientWatchCallBack(SimpleClient client) {
+      this.client = client;
+    }
+
+    /**
+     * If the client list is modified, checks if the current is still in the list. otherwise, readds ti.
+     * @return true to enable watcher, or false to disable it in future WatcherThread cycles.
+     */
+    public boolean handleWatchEvent(WatcherElement watcher, Lock lock) {
+      boolean isWatchEnable = watcher.isWatchEnabled();
+      if (lock == null)//no update on the list
+        return isWatchEnable;
+      log.debug("change on the client list ");
+      if (client != null) {
+
+        //checks if the client is not already in the lists
+        ClientHandle[] cl = clist.retrieveClientList(lock);//clist.retrieveClientList();
+        boolean found = false;
+        if (cl != null) {
+          for (int chi = cl.length - 1; !found && chi > -1; chi--) {
+            found = cl[chi].equals(this.client.getClientHandle());
+          }
 
-            }
-          log.debug("isWatchEnable "+isWatchEnable);
-          return isWatchEnable;
         }
+        if (!found) {
+          log.debug("client not in the list ");
+          if (log.isDebugEnabled())
+            log
+                .debug("the client has not been found in the list. Adding it again :"
+                    + cl);
+          addClient(client);
+        } else
+          log.debug("client is in the list");
+
       }
-  
-/**
- *  
- * removes a client from the current session
- *  removes the client from the session client list
- *  if the client is the last one from the session  (ClientList), the current session is removed 
- *  from active session list.
- *  
- *  The active should add them self to the client list. To insure to close the session,when the current client is the lact active client,
- *  clears  the list of clients and when two cycles to insure there is no more active client, that otherwise would have readd themself to the list
- *  
- * @param client client to remove
- */
+      log.debug("isWatchEnable " + isWatchEnable);
+      return isWatchEnable;
+    }
+  }
+
+  /**
+   *  
+   * removes a client from the current session
+   *  removes the client from the session client list
+   *  if the client is the last one from the session  (ClientList), the current session is removed 
+   *  from active session list.
+   *  
+   *  The active should add them self to the client list. To insure to close the session,when the current client is the lact active client,
+   *  clears  the list of clients and when two cycles to insure there is no more active client, that otherwise would have readd themself to the list
+   *  
+   * @param client client to remove
+   */
   protected void removeClient(SimpleClient client)//IClient client)
   {
-    if (client == null)
-      {
-        log.error("Null client passed to removeClient");
-        return;
-      }
-    ClientSessionFileWatcherElement cwe=getClientWatcherElement();
-    if (cwe!=null && cwe.isWatchEnabled()) {
-      cwe.haltWatch();
-    };
+    if (client == null) {
+      log.error("Null client passed to removeClient");
+      return;
+    }
+    //ClientSessionFileWatcherElement cwe=getClientWatcherElement();
+    //if (cwe!=null && cwe.isWatchEnabled()) {
+    //  cwe.haltWatch();
+    //};
     //set handler to check is the the last active client of the session
     //Wait for several watchers cycle to see if the current client was the last client active in the session.
     //if yes, close the session
-    
-   // getClientWatcherElement().setHandler(new RemoveClientWatchCallBack (client));
-    getClientWatcherElement().setTimeoutBeforeLastCycle(this.watchCycleCountBeforeLastClient);
+
+    // getClientWatcherElement().setHandler(new RemoveClientWatchCallBack (client));
+    // getClientWatcherElement().setTimeoutBeforeLastCycle(this.watchCycleCountBeforeLastClient);
     log.info("remove client from list");
-    clist.clearList();
+    if (clistWatchElement!=null)
+    {
+      clistWatchElement.haltWatch();
+      clistWatchElement.watched.unlockFile();
+    }
+    //clist.clearList();
+    //clist.unlockFile();
     log.info("list cleared");
-    if (cwe!=null) {
-      cwe.enableWatch();
-      
-      
-      log.debug("Stopping EventGenerator..");
-      client.evgen.stopWatching();
-      cwe.setHandler(null);
-      
-      // ask to the client to copy application data into the document
-      client.evgen._raise(Events.DOCUMENT_FINALIZEAPPDATA, null, client,null);
-      boolean closeSession=isLastActiveClient(client);
-      if (closeSession)
-      {
-        log.debug("Raising request-to-save event");
-        client.evgen._raise(Events.DOCUMENT_REQUESTTOCLOSE, null, client, null);
-        client.evgen._raise(Events.SESSION_SHUTDOWN, null, client.getSessionHandle(), null);
-      }
-      try 
-        {
-          log.debug("Attempting to release active client locks");
-          client.releaseActiveClientFile();
-        }
-      catch (IOException e)
-        {
-          log.error("error during active file client release");
-         }
-      if (closeSession)
-      {
-        log.debug("Last active client: closing session");
-        log.info("Closing session");
-          getSessionManager().removeSession(client.getSessionHandle());
-      }
+    //if (cwe!=null) {
+    // cwe.enableWatch();
+
+    log.debug("Stopping EventGenerator..");
+    client.evgen.stopWatching();
+    // cwe.setHandler(null);
+    // ask to the client to copy application data into the document
+    client.evgen._raise(Events.DOCUMENT_FINALIZEAPPDATA, null, client, null);
+    boolean closeSession = isLastActiveClient(client);
+    if (closeSession) {
+      log.debug("Raising request-to-save event");
+      client.evgen._raise(Events.DOCUMENT_REQUESTTOCLOSE, null, client, null);
+      client.evgen._raise(Events.SESSION_SHUTDOWN, null, client
+          .getSessionHandle(), null);
+    }
+    //cwe.haltWatch();
+    client.evgen.stopWatching();
+    try {
+      log.debug("Attempting to release active client locks");
+      client.releaseActiveClientFile();
+    } catch (IOException e) {
+      log.error("error during active file client release");
+    }
+    tidyUp();
+    if (closeSession) {
+      log.debug("Last active client: closing session");
+      log.info("Closing session");
+      getSessionManager().removeSession(client.getSessionHandle());
     }
   }
-  
-  
-  private boolean isLastActiveClient(SimpleClient client)
-    {
+
+  /**
+   * close every file and stop.
+   */
+  private void tidyUp() {
+    if (clist != null)
+      clist.unlockFile();
+    clist = null;
+    storedocfile.unlockFile();
+    storedocfile = null;
+    closeSessionLog();
+  }
+
+  private boolean isLastActiveClient(SimpleClient client) {
     log.debug("Testing if current client is the last one.");
-    log.debug("current client lockfile is '"+client.getClientlockFile()+"'");
-      boolean noOtherActiveClient = true;
-      //create, if need,  subdirectory to contain client files
-      File clientlockFileDir = new File (this.sessionDir, clientFileDirectory);
-      if( !clientlockFileDir.exists())
-        {
-          log.error("Something wrong the active client file does not exits... should not happen");
-          return false;
+    log
+        .debug("current client lockfile is '" + client.getClientlockFile()
+            + "'");
+    boolean noOtherActiveClient = true;
+    //create, if need,  subdirectory to contain client files
+    File clientlockFileDir = new File(this.sessionDir, clientFileDirectory);
+    if (!clientlockFileDir.exists()) {
+      log
+          .error("Something wrong the active client file does not exits... should not happen");
+      return false;
+    }
+
+    try {
+
+      //no check every file in the directory and try to get lock on it.
+      File[] clientFiles = clientlockFileDir.listFiles();
+      if (clientFiles == null || clientFiles.length == 0) {//there is not file on the directory. the current client should be the last one.
+        return true;
+      }
+
+      for (int i = clientFiles.length - 1; i > -1 && noOtherActiveClient; i--) {
+        File clientFile = clientFiles[i];
+        log.debug("testing file for lock: " + clientFile.getAbsolutePath());
+        if (client.getClientLock().isTargetLockFile(clientFile)) {
+          log.debug("current client file found");
+          continue;
         }
-      
-      try {
-    
-        //no check every file in the directory and try to get lock on it.
-        File [] clientFiles = clientlockFileDir.listFiles();
-        if(clientFiles == null || clientFiles.length==0)
-          {//there is not file on the directory. the current client should be the last one.
-            return true;
-          }
-       
-        for (int i = clientFiles.length - 1; i>-1&& noOtherActiveClient  ;i--)
-          {
-             File clientFile = clientFiles[i];
-             log.debug("testing file for lock: "+clientFile.getAbsolutePath());
-             if(client.getClientLock().isTargetLockFile(clientFile)) 
-               {
-               log.debug("current client file found");
-                 continue;
-               }
-             if (clientFile != null &&  clientFile.exists() )
-             {
-               try
-                 {
-                 log.debug("Try to acquire a lock on the file");
-                 // Get a file channel for the file
-                   FileChannel channel = new RandomAccessFile(clientFile, "rw").getChannel();
-         
-                 // Use the file channel to create a lock on the file.
-                 // This method blocks until it can retrieve the lock.
-                 //  java.nio.channels.FileLock activeClientFilelock = channel.lock();
-         
-                 // Try acquiring the lock without blocking. This method returns
-                 // null or throws an exception if the file is already locked.
-                   try
-                     {
-                     java.nio.channels.FileLock  activeClientFilelock = channel.tryLock();
-                     
-                       //the lock has been acquired. 
-                       //the file was not lock and so the corresponding application seems to have die
-                     if(activeClientFilelock != null)
-                       {
-                         log.debug("lock obtained : file must be from a crashed application");
-                         
-                     
-                         activeClientFilelock.release();
-                         log.debug("lock released");
-                         
-                         channel.close();
-                         log.debug("channel closed");
-                         
-                       //delete file 
-                         clientFile.delete();
-                         log.debug("crashed application file deleted");
-                         
-                       }
-                     else
-                       {
-                       noOtherActiveClient  = false;
-                         log.debug("lock not obtained : another application is active");
-                       }
-                     }
-                   catch (OverlappingFileLockException e) 
-                     {
-                     // File is already locked in this thread or virtual machine
-                     //that the expected behaviour
-                     log.debug("lock not accessible ",e);
-                     }
-                 } 
-               catch (Exception e) 
-                 {
-                 log.debug("error during lock testing ",e);
-                 }
-             }
+        if (clientFile != null && clientFile.exists()) {
+          try {
+            log.debug("Try to acquire a lock on the file");
+            // Get a file channel for the file
+            FileChannel channel = new RandomAccessFile(clientFile, "rw")
+                .getChannel();
+
+            // Use the file channel to create a lock on the file.
+            // This method blocks until it can retrieve the lock.
+            //  java.nio.channels.FileLock activeClientFilelock = channel.lock();
+
+            // Try acquiring the lock without blocking. This method returns
+            // null or throws an exception if the file is already locked.
+            try {
+              java.nio.channels.FileLock activeClientFilelock = channel
+                  .tryLock();
+
+              //the lock has been acquired. 
+              //the file was not lock and so the corresponding application seems to have die
+              if (activeClientFilelock != null) {
+                log
+                    .debug("lock obtained : file must be from a crashed application");
+
+                activeClientFilelock.release();
+                log.debug("lock released");
+
+                channel.close();
+                log.debug("channel closed");
+
+                //delete file 
+                clientFile.delete();
+                log.debug("crashed application file deleted");
+
+              } else {
+                noOtherActiveClient = false;
+                log.debug("lock not obtained : another application is active");
+              }
+            } catch (OverlappingFileLockException e) {
+              // File is already locked in this thread or virtual machine
+              //that the expected behaviour
+              log.debug("lock not accessible ", e);
+            }
+          } catch (Exception e) {
+            log.debug("error during lock testing ", e);
           }
-      
-      } catch (Exception e) {
-       log.error("error during counting active clients");
+        }
       }
-      return noOtherActiveClient;
+
+    } catch (Exception e) {
+      log.error("error during counting active clients");
     }
+    return noOtherActiveClient;
+  }
+
   /**
    * Handler for the client watcher. after a client have been removed
    * 
    * Checks if the client is not the last active one.
    * 
    * If (the current client is not in the client list readd it;)
-   */  
-  private class RemoveClientWatchCallBack  implements WatcherCallBack
-  {
-   
-    private SimpleClient client ;
+   */
+  private class RemoveClientWatchCallBack implements WatcherCallBack {
+
+    private SimpleClient client;
+
     private boolean manualCheckOfClientCount = false;
+
     /**
-    *Inits the handler with the client to check in the list
+     *Inits the handler with the client to check in the list
      * @param client client to monitor in the client list
      */
-    protected  RemoveClientWatchCallBack (SimpleClient client)
-      {
-        this.client = client;
-      }
-    
-      /**
-       * If the client list is modified, checks if the current is still in the list. otherwise, readds ti.
-       * @return true to enable watcher, or false to disable it in future WatcherThread cycles.
-       */
-      public boolean handleWatchEvent(WatcherElement watcher, Lock lock)
-        { 
-        // if lock is null, no client has been added since last, clear.
-        //the client is then the last client
-          if (client != null)
-            {
-           
-              if (lock == null )
-              {
-            
+    protected RemoveClientWatchCallBack(SimpleClient client) {
+      this.client = client;
+    }
+
+    /**
+     * If the client list is modified, checks if the current is still in the list. otherwise, readds ti.
+     * @return true to enable watcher, or false to disable it in future WatcherThread cycles.
+     */
+    public boolean handleWatchEvent(WatcherElement watcher, Lock lock) {
+      // if lock is null, no client has been added since last, clear.
+      //the client is then the last client
+      if (client != null) {
+
+        if (lock == null) {
+
+          //checks if the client is not already in the lists
+          //   ClientHandle[] cl = clist.retrieveClientList();//lock);//clist.retrieveClientList();
+
+          boolean islastClient = true;
+          if (manualCheckOfClientCount) {
+            log.debug("manual checking of count of client");
             //checks if the client is not already in the lists
-           //   ClientHandle[] cl = clist.retrieveClientList();//lock);//clist.retrieveClientList();
-
-              boolean islastClient =  true;
-              if (manualCheckOfClientCount)
-                {
-                log.debug("manual checking of count of client");
-  //checks if the client is not already in the lists
-                  ClientHandle[] cl = clist.retrieveClientList();//lock);//clist.retrieveClientList();
-                  if(cl == null || cl.length<1 )
-       //  {//no client has registered as active 
-                  {
-                    islastClient = true;
-                    log.debug("list is empty");
-                  }
-                  else
-                    islastClient = false;
-                  log.debug("list is not empty");
-                }
-            //  if(cl == null || cl.length<1 )
-              //  {//no client has registered as active
-              if (islastClient)
-              {
-                //the client is the last one, so close current session
-                  log.info("last client removed: closing session");
-                  closeSession(client);
-              }
-            }
-              else
-              {
-                log.debug("not the last client found ");
-//              ask to the client to cpoy application data into the document
-       //         client.evgen._raise(Events.DOCUMENT_FINALIZEAPPDATA, null, client,null);
-
-           //   /  }
-         
-            }
-              log.debug("Stopping EventGenerator..");
-              // TODO: ensure ClientsFile lock is really released!! clist.unlockFile();
-          client.evgen.stopWatching();
-        }
-          watcher.setHandler(null);//Do not check if the client is the last client. watcher will shutdown anyway
-        //  watcher.haltWatch();
-         // watcher.
-          return false;
+            ClientHandle[] cl = clist.retrieveClientList();//lock);//clist.retrieveClientList();
+            if (cl == null || cl.length < 1)
+            //  {//no client has registered as active 
+            {
+              islastClient = true;
+              log.debug("list is empty");
+            } else
+              islastClient = false;
+            log.debug("list is not empty");
+          }
+          //  if(cl == null || cl.length<1 )
+          //  {//no client has registered as active
+          if (islastClient) {
+            //the client is the last one, so close current session
+            log.info("last client removed: closing session");
+            closeSession(client);
+          }
+        } else {
+          log.debug("not the last client found ");
+          //              ask to the client to cpoy application data into the document
+          //         client.evgen._raise(Events.DOCUMENT_FINALIZEAPPDATA, null, client,null);
+
+          //   /  }
+
         }
+        log.debug("Stopping EventGenerator..");
+        // TODO: ensure ClientsFile lock is really released!! clist.unlockFile();
+        client.evgen.stopWatching();
       }
+      watcher.setHandler(null);//Do not check if the client is the last client. watcher will shutdown anyway
+      //  watcher.haltWatch();
+      // watcher.
+      return false;
+    }
+  }
 
   /**
    * closes the current session, 
    * and send an event to the last client to close the document
    * @param client the last client of the client
    */
-  private void closeSession(SimpleClient client)
-    {
-//   close document 
-      client.evgen._raise(Events.DOCUMENT_REQUESTTOCLOSE, null, client,null);
-      log.debug("close document request done");
-      closeSession(client.getSessionHandle());
-    }
-  
+  private void closeSession(SimpleClient client) {
+    //   close document 
+    client.evgen._raise(Events.DOCUMENT_REQUESTTOCLOSE, null, client, null);
+    log.debug("close document request done");
+    closeSession(client.getSessionHandle());
+  }
+
   /**
    * CLoses the current session
    * @param sessionHandle sessionHandle of the session to remove
    */
-  private void closeSession(SessionHandle sessionHandle)
-    {
-      getSessionManager().removeSession(sessionHandle);
-      log.debug("Session removed");
-    }
-/**
- * @return the sessionManager
- */
-protected SimpleSessionManager getSessionManager() {
-  return sessionManager;
-}
-/**
- * @param sessionManager the sessionManager to set
- */
-protected void setSessionManager(SimpleSessionManager sessionManager) {
-  this.sessionManager = sessionManager;
-}
-public ClientsFile getStoreDocFile() {
-  if (storedocfile==null) {
-    
+  private void closeSession(SessionHandle sessionHandle) {
+    getSessionManager().removeSession(sessionHandle);
+    log.debug("Session removed");
   }
-  return storedocfile;
-}
 
-ClientSessionFileWatcherElement clistWatchElement=null;
-public ClientSessionFileWatcherElement getClientWatcherElement() {
-  if (clistWatchElement==null) {
-    clistWatchElement=new ClientSessionFileWatcherElement(clist,null);
+  /**
+   * @return the sessionManager
+   */
+  protected SimpleSessionManager getSessionManager() {
+    return sessionManager;
   }
-  return clistWatchElement;
-}
-/**
- * writes a vector of vorba Ids to the session.
- * @param modObjects 
-public void setModObjectList(Vector modObjects) {
-  log.debug("Writing "+modObjects.size()+" ids to ModObjectList");
-  // TODO Auto-generated method stub
-}
-**
- * get current list of modified objects.
- * @return null or Vector of objects
- *
-public Vector getModObjectList() {
-  log.debug("Reading modObjectList");
-  return null;
-}
-*/
-}
 
+  /**
+   * @param sessionManager the sessionManager to set
+   */
+  protected void setSessionManager(SimpleSessionManager sessionManager) {
+    this.sessionManager = sessionManager;
+  }
+
+  public ClientsFile getStoreDocFile() {
+    if (storedocfile == null) {
+
+    }
+    return storedocfile;
+  }
+
+  ClientSessionFileWatcherElement clistWatchElement = null;
 
+  /**
+   * get or create a watcher on clist.
+   * @return the contents of clistWatchElement or initialise it
+   */
+  public ClientSessionFileWatcherElement getClientWatcherElement() {
+    if (clistWatchElement == null) {
+      clistWatchElement = new ClientSessionFileWatcherElement(clist, null);
+    }
+    return clistWatchElement;
+  }
+  /**
+   * writes a vector of vorba Ids to the session.
+   * @param modObjects 
+   public void setModObjectList(Vector modObjects) {
+   log.debug("Writing "+modObjects.size()+" ids to ModObjectList");
+   // TODO Auto-generated method stub
+   }
+   **
+   * get current list of modified objects.
+   * @return null or Vector of objects
+   *
+   public Vector getModObjectList() {
+   log.debug("Reading modObjectList");
+   return null;
+   }
+   */
+}