applied LGPLv3 and source code formatting.
[vamsas.git] / src / uk / ac / vamsas / client / simpleclient / SessionFile.java
index aa5e779..0c35fe2 100644 (file)
-package uk.ac.vamsas.client.simpleclient;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.nio.channels.ReadableByteChannel;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Basic methods for classes handling locked IO on files 
- * monitored by all (simpleclient) clients in a vamsas session.
- * @author jimp
- *TODO: support non nio file locking capable systems
- */
-public class SessionFile {
-  private static Log log = LogFactory.getLog(SessionFile.class);
-  protected File sessionFile;
-  protected Lock fileLock = null;
-
-  protected SessionFile(File file) {
-    super();
-    sessionFile = file;
-  }
-
-  protected boolean lockFile(Lock extantlock) {
-    if (fileLock!=null && !fileLock.isLocked()) {
-      fileLock.release();// tidy up invalid lock
-      fileLock=null;
-    }
-    if (extantlock!=null && extantlock.isLocked())
-      fileLock=extantlock; // THIS IS BROKEN - lockFile then nulls the lock.
-    return lockFile();
-  }
-  private boolean ensureSessionFile() {
-    if (sessionFile != null) {
-      if (!sessionFile.exists()) {
-        // create new file
-        try {
-          if (!sessionFile.createNewFile()) {
-            log.error("Failed to create file prior to locking: "+sessionFile);
-            return false;
-          }
-        } catch (IOException e) {
-          log.error("Exception when trying to create file "+sessionFile, e);
-          return false;
-        }
-      }
-      return true;
-    }
-    log.error("ensureSessionFile called for non-initialised SessionFile!");
-    return false;
-  }
-  /**
-   * Get a lock for the SessionFile
-   * 
-   * @return true if lock was made
-   */
-  protected boolean lockFile() {
-    if (fileLock != null) {
-      if (fileLock.isLocked()) {
-        if (!ensureSessionFile())
-          return false;
-        return true;
-      } else {
-        // lock failed for some reason.
-        fileLock.release();
-        log.info("Unexpected session file lock failure. Trying to get it again.");
-        fileLock=null;
-      }
-    }
-    if (!ensureSessionFile())
-      return false;
-    // TODO: see if we need to loop-wait for locks or they just block until
-    // lock is made...
-    long tries=5000;
-    do {
-      tries--;
-      if (fileLock==null || !fileLock.isLocked()) {
-        //try { Thread.sleep(1); } catch (Exception e) {};
-        fileLock = LockFactory.getLock(sessionFile,true); // TODO: wait around if we can't get the lock.
-          }
-      } while (tries>0 && !fileLock.isLocked());
-    if (!fileLock.isLocked())
-      log.error("Failed to get lock for "+sessionFile);
-    // fileLock = new Lock(sessionFile);
-    return fileLock.isLocked();    
-  }
-
-  /**
-   * Explicitly release the SessionFile's lock.
-   * 
-   * @return true if lock was released.
-   */
-  protected void unlockFile() {
-    if (fileLock != null) {
-      fileLock.release();    
-      fileLock = null;
-    }
-  }
-
-  /**
-   * Makes a backup of the sessionFile.
-   * @return Backed up SessionFile or null if failed to make backup.
-   */
-  protected File backupSessionFile() {
-    return backupSessionFile(fileLock, sessionFile.getName(),".old", sessionFile.getParentFile());
-  }
-
-  protected File backupSessionFile(Lock extantLock, String backupPrefix, String backupSuffix, File backupDir) {
-    File tempfile=null;
-    if (lockFile(extantLock)) {
-      try {
-        tempfile = File.createTempFile(backupPrefix, backupSuffix, backupDir);
-        long sourceln = fileLock.length();
-        if (sourceln>0) {
-          FileOutputStream tos = new FileOutputStream(tempfile);
-          ReadableByteChannel channel;
-          channel = fileLock.getRaChannel().position(0);
-          long ntrans = 0;
-          while (ntrans<sourceln)
-          {
-            long tlen;
-            ntrans+= tlen = tos.getChannel().transferFrom(channel, ntrans,
-              sourceln);
-            if (log.isDebugEnabled())
-            {
-              log.debug
-              ("Transferred "+tlen+" out of "+sourceln+" bytes");
-            }
-          }
-          tos.close();
-          if (!channel.isOpen())
-            throw new Error("LIBRARY PORTABILITY ISSUE: "+tos.getChannel().getClass()+".transferFrom closes source channel!");
-          if (!lockFile(extantLock))
-            throw new Error("LIBRARY PORTABILITY ISSUE: Lost lock for "+sessionFile.getName()+" after backup.");
-          
-        }
-      } catch (FileNotFoundException e1) {
-        log.warn("Can't create temp file for "+sessionFile.getName(),e1);
-        tempfile=null;
-      } catch (IOException e1) {
-        log.warn("Error when copying content to temp file for "+sessionFile.getName(),e1);
-        tempfile=null;
-      }
-    }
-    return tempfile;
-  }
-  /**
-   * Replaces data in sessionFile with data from file handled by another sessionFile
-   * passes up any exceptions.
-   * @param newData source for new data
-   */
-  protected void updateFrom(Lock extantLock, SessionFile newData) throws IOException {
-    log.debug("Updating "+sessionFile.getAbsolutePath()+" from "+newData.sessionFile.getAbsolutePath());
-    if (newData==null)
-      throw new IOException("Null newData object.");
-    if (newData.sessionFile==null)
-      throw new IOException("Null SessionFile in newData.");
-      
-    if (!lockFile(extantLock))
-      throw new IOException("Failed to get write lock for "+sessionFile);
-    if (!newData.lockFile())
-      throw new IOException("Failed to get lock for updateFrom "+newData.sessionFile);
-    RandomAccessFile nrafile = newData.fileLock.getRaFile();
-    nrafile.seek(0);
-    RandomAccessFile trafile = fileLock.getRaFile();
-    /*long tries=5000;
-    while (trafile==null && --tries>0) {
-      log.debug("Lost lock on "+sessionFile+"! Re-trying for a transfer.");
-      lockFile();
-      trafile = fileLock.getRaFile();
-    }*/
-    // TODO JBPNote: attempt to ensure save really saves the VamDoc.jar file
-    trafile.seek(0);
-    trafile.getChannel().transferFrom(nrafile.getChannel(), 0, 
-        nrafile.length());
-    // JBPNote: attempt to close the streams to flush the data out
-    // trafile.close();
-    //nrafile.close();
-  }
-  /**
-   * remove all trace of the sessionFile file
-   *
-   */
-  protected void eraseExistence() {
-    unlockFile();
-    if (sessionFile!=null) {
-      sessionFile.delete();
-      sessionFile = null;
-    }
-  }
-  /* (non-Javadoc)
-   * @see uk.ac.vamsas.client.simpleclient.Lock#getBufferedInputStream(boolean)
-   */
-  public BufferedInputStream getBufferedInputStream(boolean atStart) throws IOException {
-    lockFile();
-    return fileLock.getBufferedInputStream(atStart);
-  }
-
-  /* (non-Javadoc)
-   * @see uk.ac.vamsas.client.simpleclient.Lock#getBufferedOutputStream(boolean)
-   */
-  public BufferedOutputStream getBufferedOutputStream(boolean clear) throws IOException {
-    lockFile();
-    return fileLock.getBufferedOutputStream(clear);
-  }
-
-  /* (non-Javadoc)
-   * @see uk.ac.vamsas.client.simpleclient.Lock#getFileInputStream(boolean)
-   */
-  public FileInputStream getFileInputStream(boolean atStart) throws IOException {
-    lockFile();
-    return fileLock.getFileInputStream(atStart);
-  }
-
-  /* (non-Javadoc)
-   * @see uk.ac.vamsas.client.simpleclient.Lock#getFileOutputStream(boolean)
-   */
-  public FileOutputStream getFileOutputStream(boolean clear) throws IOException {
-    lockFile();
-    return fileLock.getFileOutputStream(clear);
-  }
-  
-}
+/*\r
+ * This file is part of the Vamsas Client version 0.1. \r
+ * Copyright 2009 by Jim Procter, Iain Milne, Pierre Marguerite, \r
+ *  Andrew Waterhouse and Dominik Lindner.\r
+ * \r
+ * Earlier versions have also been incorporated into Jalview version 2.4 \r
+ * since 2008, and TOPALi version 2 since 2007.\r
+ * \r
+ * The Vamsas Client is free software: you can redistribute it and/or modify\r
+ * it under the terms of the GNU Lesser General Public License as published by\r
+ * the Free Software Foundation, either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ *  \r
+ * The Vamsas Client is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\r
+ * GNU Lesser General Public License for more details.\r
+ * \r
+ * You should have received a copy of the GNU Lesser General Public License\r
+ * along with the Vamsas Client.  If not, see <http://www.gnu.org/licenses/>.\r
+ */\r
+package uk.ac.vamsas.client.simpleclient;\r
+\r
+import java.io.BufferedInputStream;\r
+import java.io.BufferedOutputStream;\r
+import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.FileNotFoundException;\r
+import java.io.FileOutputStream;\r
+import java.io.IOException;\r
+import java.io.RandomAccessFile;\r
+import java.nio.channels.ReadableByteChannel;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+\r
+/**\r
+ * Basic methods for classes handling locked IO on files monitored by all\r
+ * (simpleclient) clients in a vamsas session.\r
+ * \r
+ * @author jimp TODO: support non nio file locking capable systems\r
+ */\r
+public class SessionFile {\r
+  private static Log log = LogFactory.getLog(SessionFile.class);\r
+\r
+  protected File sessionFile;\r
+\r
+  protected Lock fileLock = null;\r
+\r
+  protected SessionFile(File file) {\r
+    super();\r
+    sessionFile = file;\r
+  }\r
+\r
+  protected boolean lockFile(Lock extantlock) {\r
+    if (fileLock != null && !fileLock.isLocked()) {\r
+      fileLock.release();// tidy up invalid lock\r
+      fileLock = null;\r
+    }\r
+    if (extantlock != null && extantlock.isLocked())\r
+      fileLock = extantlock; // THIS IS BROKEN - lockFile then nulls the lock.\r
+    return lockFile();\r
+  }\r
+\r
+  private boolean ensureSessionFile() {\r
+    if (sessionFile != null) {\r
+      if (!sessionFile.exists()) {\r
+        // create new file\r
+        try {\r
+          if (!sessionFile.createNewFile()) {\r
+            log.error("Failed to create file prior to locking: " + sessionFile);\r
+            return false;\r
+          }\r
+        } catch (IOException e) {\r
+          log.error("Exception when trying to create file " + sessionFile, e);\r
+          return false;\r
+        }\r
+      }\r
+      return true;\r
+    }\r
+    log.error("ensureSessionFile called for non-initialised SessionFile!");\r
+    return false;\r
+  }\r
+\r
+  /**\r
+   * Get a lock for the SessionFile\r
+   * \r
+   * @return true if lock was made\r
+   */\r
+  protected boolean lockFile() {\r
+    if (fileLock != null) {\r
+      if (fileLock.isLocked()) {\r
+        if (!ensureSessionFile())\r
+          return false;\r
+        return true;\r
+      } else {\r
+        // lock failed for some reason.\r
+        fileLock.release();\r
+        log\r
+            .info("Unexpected session file lock failure. Trying to get it again.");\r
+        fileLock = null;\r
+      }\r
+    }\r
+    if (!ensureSessionFile())\r
+      return false;\r
+    // TODO: see if we need to loop-wait for locks or they just block until\r
+    // lock is made...\r
+    long tries = 5000;\r
+    do {\r
+      tries--;\r
+      if (fileLock == null || !fileLock.isLocked()) {\r
+        // try { Thread.sleep(1); } catch (Exception e) {};\r
+        fileLock = LockFactory.getLock(sessionFile, true); // TODO: wait around\r
+                                                           // if we can't get\r
+                                                           // the lock.\r
+      }\r
+    } while (tries > 0 && !fileLock.isLocked());\r
+    if (!fileLock.isLocked())\r
+      log.error("Failed to get lock for " + sessionFile);\r
+    // fileLock = new Lock(sessionFile);\r
+    return fileLock.isLocked();\r
+  }\r
+\r
+  /**\r
+   * Explicitly release the SessionFile's lock.\r
+   * \r
+   * @return true if lock was released.\r
+   */\r
+  protected void unlockFile() {\r
+    if (fileLock != null) {\r
+      fileLock.release();\r
+      fileLock = null;\r
+    }\r
+  }\r
+\r
+  /**\r
+   * Makes a backup of the sessionFile.\r
+   * \r
+   * @return Backed up SessionFile or null if failed to make backup.\r
+   */\r
+  protected File backupSessionFile() {\r
+    return backupSessionFile(fileLock, sessionFile.getName(), ".old",\r
+        sessionFile.getParentFile());\r
+  }\r
+\r
+  protected File backupSessionFile(Lock extantLock, String backupPrefix,\r
+      String backupSuffix, File backupDir) {\r
+    File tempfile = null;\r
+    if (lockFile(extantLock)) {\r
+      try {\r
+        tempfile = File.createTempFile(backupPrefix, backupSuffix, backupDir);\r
+        long sourceln = fileLock.length();\r
+        if (sourceln > 0) {\r
+          FileOutputStream tos = new FileOutputStream(tempfile);\r
+          ReadableByteChannel channel;\r
+          channel = fileLock.getRaChannel().position(0);\r
+          long ntrans = 0;\r
+          while (ntrans < sourceln) {\r
+            long tlen;\r
+            ntrans += tlen = tos.getChannel().transferFrom(channel, ntrans,\r
+                sourceln);\r
+            if (log.isDebugEnabled()) {\r
+              log.debug("Transferred " + tlen + " out of " + sourceln\r
+                  + " bytes");\r
+            }\r
+          }\r
+          tos.close();\r
+          if (!channel.isOpen())\r
+            throw new Error("LIBRARY PORTABILITY ISSUE: "\r
+                + tos.getChannel().getClass()\r
+                + ".transferFrom closes source channel!");\r
+          if (!lockFile(extantLock))\r
+            throw new Error("LIBRARY PORTABILITY ISSUE: Lost lock for "\r
+                + sessionFile.getName() + " after backup.");\r
+\r
+        }\r
+      } catch (FileNotFoundException e1) {\r
+        log.warn("Can't create temp file for " + sessionFile.getName(), e1);\r
+        tempfile = null;\r
+      } catch (IOException e1) {\r
+        log.warn("Error when copying content to temp file for "\r
+            + sessionFile.getName(), e1);\r
+        tempfile = null;\r
+      }\r
+    }\r
+    return tempfile;\r
+  }\r
+\r
+  /**\r
+   * Replaces data in sessionFile with data from file handled by another\r
+   * sessionFile passes up any exceptions.\r
+   * \r
+   * @param newData\r
+   *          source for new data\r
+   */\r
+  protected void updateFrom(Lock extantLock, SessionFile newData)\r
+      throws IOException {\r
+    log.debug("Updating " + sessionFile.getAbsolutePath() + " from "\r
+        + newData.sessionFile.getAbsolutePath());\r
+    if (newData == null)\r
+      throw new IOException("Null newData object.");\r
+    if (newData.sessionFile == null)\r
+      throw new IOException("Null SessionFile in newData.");\r
+\r
+    if (!lockFile(extantLock))\r
+      throw new IOException("Failed to get write lock for " + sessionFile);\r
+    if (!newData.lockFile())\r
+      throw new IOException("Failed to get lock for updateFrom "\r
+          + newData.sessionFile);\r
+    RandomAccessFile nrafile = newData.fileLock.getRaFile();\r
+    nrafile.seek(0);\r
+    RandomAccessFile trafile = fileLock.getRaFile();\r
+    /*\r
+     * long tries=5000; while (trafile==null && --tries>0) {\r
+     * log.debug("Lost lock on "+sessionFile+"! Re-trying for a transfer.");\r
+     * lockFile(); trafile = fileLock.getRaFile(); }\r
+     */\r
+    // TODO JBPNote: attempt to ensure save really saves the VamDoc.jar file\r
+    trafile.seek(0);\r
+    trafile.getChannel()\r
+        .transferFrom(nrafile.getChannel(), 0, nrafile.length());\r
+    // JBPNote: attempt to close the streams to flush the data out\r
+    // trafile.close();\r
+    // nrafile.close();\r
+  }\r
+\r
+  /**\r
+   * remove all trace of the sessionFile file\r
+   * \r
+   */\r
+  protected void eraseExistence() {\r
+    unlockFile();\r
+    if (sessionFile != null) {\r
+      sessionFile.delete();\r
+      sessionFile = null;\r
+    }\r
+  }\r
+\r
+  /*\r
+   * (non-Javadoc)\r
+   * \r
+   * @see uk.ac.vamsas.client.simpleclient.Lock#getBufferedInputStream(boolean)\r
+   */\r
+  public BufferedInputStream getBufferedInputStream(boolean atStart)\r
+      throws IOException {\r
+    lockFile();\r
+    return fileLock.getBufferedInputStream(atStart);\r
+  }\r
+\r
+  /*\r
+   * (non-Javadoc)\r
+   * \r
+   * @see uk.ac.vamsas.client.simpleclient.Lock#getBufferedOutputStream(boolean)\r
+   */\r
+  public BufferedOutputStream getBufferedOutputStream(boolean clear)\r
+      throws IOException {\r
+    lockFile();\r
+    return fileLock.getBufferedOutputStream(clear);\r
+  }\r
+\r
+  /*\r
+   * (non-Javadoc)\r
+   * \r
+   * @see uk.ac.vamsas.client.simpleclient.Lock#getFileInputStream(boolean)\r
+   */\r
+  public FileInputStream getFileInputStream(boolean atStart) throws IOException {\r
+    lockFile();\r
+    return fileLock.getFileInputStream(atStart);\r
+  }\r
+\r
+  /*\r
+   * (non-Javadoc)\r
+   * \r
+   * @see uk.ac.vamsas.client.simpleclient.Lock#getFileOutputStream(boolean)\r
+   */\r
+  public FileOutputStream getFileOutputStream(boolean clear) throws IOException {\r
+    lockFile();\r
+    return fileLock.getFileOutputStream(clear);\r
+  }\r
+\r
+}\r