+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;
+
+public class NativeLock extends Lock {
+
+ protected FileLock lock = null;
+
+ /**
+ * @param lockfile
+ */
+ public NativeLock(File lockfile) {
+ super(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);
+ }
+ }
+
+ public boolean isLocked() {
+ if (lock != null && lock.isValid()) {
+ return true;
+ }
+ return false;
+ }
+
+ 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.getFD().valid() && rafile.getChannel()!=null && lock.isValid()) {
+ if (closeChannel && rafile.getChannel().isOpen()) {
+ rafile.close();
+ rafile=null;
+ }
+ if (lock!=null && lock.isValid())
+ lock.release();
+
+ }
+ } catch (IOException e) {
+ log.warn("Whilst releasing lock",e);
+ }
+ lock=null;
+ }
+
+ /**
+ * 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());
+ }
+
+ /**
+ * gets Locked stream to write to
+ * FileInput always starts at the *end* of the file (after any truncation)
+ * @param clear true means file will be cleared to zero length
+ * @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());
+ }
+
+ /**
+ * 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;
+ }
+ /**
+ * @see org.vamsas.client.simpleclient.Lock#finalize()
+ */
+ protected void finalize() throws Throwable {
+ release(true); // we explicitly lose the lock here.
+ // log.debug("lock closing through garbage collection ?");
+ super.finalize();
+ }
+
+}