introducing Lock File based locking (for portability) - part implemented.
[vamsas.git] / src / org / vamsas / client / simpleclient / Lock.java
index 903214d..9dd472f 100644 (file)
@@ -2,101 +2,57 @@ package org.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.FileLock;
 
 import org.apache.commons.logging.LogFactory;
 
 /**
  * transient object representing a file lock
  * This lock should hold for all processes interacting in a session.
- * TODO: currently implemented for local filesystem style locking - need a fallback mechanism for systems without file locks.
  * @author jimp
- * 
  */
 
-public class Lock {
-  org.apache.commons.logging.Log log = LogFactory.getLog(Lock.class);
-  FileLock lock = null;
-  RandomAccessFile rafile=null;
+public abstract class Lock {
+  protected org.apache.commons.logging.Log log = LogFactory.getLog(Lock.class);
+  File target = null; // The file that is being locked
+  protected RandomAccessFile rafile=null;
+  
   /**
    * creates a valid Lock (test with <method>isLocked</method>)
    * if a lock could be obtained for <param>lockfile</param>
    * @param lockfile
    */
-  public Lock(java.io.File lockfile) {
-    // try and get a lock.
-    lock = null;
-    
-    try {
-      if (!lockfile.exists())
-        if (!lockfile.createNewFile()) {
-          log.warn("Failed to create locked file "+lockfile);
-          return;
-        }
-      
-      lock = (rafile=new RandomAccessFile(lockfile,"rw")).getChannel().tryLock();
-      if (lock==null || !lock.isValid()) {
-        // failed to get lock. Close the file channel
-        log.debug("failed to get lock for "+lockfile);
-        rafile.getChannel().close();
-        lock=null;
-      }
-    } catch (FileNotFoundException e) {
-      //
-      log.debug("Lock failed - normal behaviour for windows locking.");
-      //log.error("Error! Couldn't create a lockfile at "
-      //  + lockfile.getAbsolutePath(), e);
-    } catch (IOException e) {
-      log.error("Error! Problems with IO when creating a lock on "
-          + lockfile.getAbsolutePath(),e);
-    }
-  }
-  
-  boolean isLocked() {
-    if (lock != null && lock.isValid()) {
-      return true;
-    }
-    return false;
+  protected Lock(java.io.File lockfile) {
+    target = lockfile;
   }
-  public void release() {
-    release(true);
-  }
-  public void release(boolean closeChannel) {
-    try {
-      // channel.close should be called before release() for rigourous locking.
-      if (rafile!=null && rafile.getChannel()!=null) {
-        if (rafile.getChannel().isOpen()) {
-          if (closeChannel && rafile.getChannel().isOpen())
-            rafile.getChannel().close();
-          if (lock!=null && lock.isValid())
-            lock.release();
-        }
-      }
-    } catch (IOException e) {
-      log.warn("Whilst releasing lock",e);
-    }
-    lock=null;
-    rafile=null; 
-  }
-  
+  /**
+   * 
+   * @return true if lock is held on the target
+   */
+  public abstract boolean isLocked();
+  /**
+   * release lock and close all managed channels to file
+   *
+   */
+  public abstract void release();
+  /**
+   * optionally close the open random access channel on the file when releasing lock
+   * @param closeChannel
+   */
+  public abstract void release(boolean closeChannel);
+
   /**
    * gets Locked Stream for reading from
    * @param atStart true to start reading at beginning of file.
    * @return null if file not locked
    * @throws IOException
    */
-  public FileInputStream getFileInputStream(boolean atStart) throws IOException {
-    if (!isLocked())
-      return null;
-    if (atStart)
-      rafile.seek(0);
-    return new FileInputStream(rafile.getFD());
-  }
+  public abstract FileInputStream getFileInputStream(boolean atStart) throws IOException;
+
   /**
    * gets Locked stream to write to
    * FileInput always starts at the *end* of the file (after any truncation)
@@ -104,26 +60,17 @@ public class Lock {
    * @return null if file is not locked
    * @throws IOException
    */
-  public FileOutputStream getFileOutputStream(boolean clear) throws IOException {
-    if (!isLocked())
-      return null;
-    if (clear)
-      rafile.setLength(0);
-    rafile.seek(rafile.length());
-    return new LockedFileOutputStream(rafile.getFD());
-  }
+  public abstract FileOutputStream getFileOutputStream(boolean clear) throws IOException;
   /**
    * return buffered output stream to locked file.
    * @param clear - true means file is truncated to 0 length before writing 
    * @return
    */
-  public BufferedOutputStream getBufferedOutputStream(boolean clear) throws IOException {
-    FileOutputStream fos = getFileOutputStream(clear);
-    if (fos!=null)
-      return new BufferedOutputStream(fos);
-    return null;
+  public abstract BufferedOutputStream getBufferedOutputStream(boolean clear) throws IOException;
+  
+  protected void finalize() throws Throwable {
+    target=null;
   }
-
   /**
    * return buffered input stream for locked file.
    * @param atStart - true means read from begining of file
@@ -135,13 +82,4 @@ public class Lock {
       return new BufferedInputStream(fis);
     return null;
   }
-  /* Explicitly release lock (probably don't need to do this!)
-   * @see java.lang.Object#finalize()
-   */
-  protected void finalize() throws Throwable {
-    release(true); // we explicitly lose the lock here.
-    // log.debug("lock closing through garbage collection ?");
-    super.finalize();
-  }
-  
 }