introducing Lock File based locking (for portability) - part implemented.
[vamsas.git] / src / org / vamsas / client / simpleclient / NativeLock.java
1 package org.vamsas.client.simpleclient;
2
3 import java.io.BufferedInputStream;
4 import java.io.BufferedOutputStream;
5 import java.io.File;
6 import java.io.FileInputStream;
7 import java.io.FileNotFoundException;
8 import java.io.FileOutputStream;
9 import java.io.IOException;
10 import java.io.RandomAccessFile;
11 import java.nio.channels.FileLock;
12
13 public class NativeLock extends Lock {
14
15   protected FileLock lock = null;
16
17   /**
18    * @param lockfile
19    */
20   public NativeLock(File lockfile) {
21     super(lockfile);
22     // try and get a lock.
23     lock = null;
24     
25     try {
26       if (!lockfile.exists())
27         if (!lockfile.createNewFile()) {
28           log.warn("Failed to create locked file "+lockfile);
29           return;
30         }
31       
32       lock = (rafile=new RandomAccessFile(lockfile,"rw")).getChannel().tryLock();
33       if (lock==null || !lock.isValid()) {
34         // failed to get lock. Close the file channel
35         log.debug("failed to get lock for "+lockfile);
36         rafile.getChannel().close();
37         lock=null;
38       }
39     } catch (FileNotFoundException e) {
40       //
41       log.debug("Lock failed - normal behaviour for windows locking.");
42       //log.error("Error! Couldn't create a lockfile at "
43       //  + lockfile.getAbsolutePath(), e);
44     } catch (IOException e) {
45       log.error("Error! Problems with IO when creating a lock on "
46           + lockfile.getAbsolutePath(),e);
47     }
48   }
49
50   public boolean isLocked() {
51     if (lock != null && lock.isValid()) {
52       return true;
53     }
54     return false;
55   }
56
57   public void release() {
58     release(true);
59   }
60
61   public void release(boolean closeChannel) {
62     try {
63       // channel.close should be called before release() for rigourous locking.
64       if (rafile!=null && rafile.getFD().valid() && rafile.getChannel()!=null && lock.isValid()) {
65         if (closeChannel && rafile.getChannel().isOpen()) {
66             rafile.close();
67             rafile=null; 
68         }
69         if (lock!=null && lock.isValid())
70           lock.release();
71         
72       }
73     } catch (IOException e) {
74       log.warn("Whilst releasing lock",e);
75     }
76     lock=null;
77   }
78
79   /**
80    * gets Locked Stream for reading from
81    * @param atStart true to start reading at beginning of file.
82    * @return null if file not locked
83    * @throws IOException
84    */
85   public FileInputStream getFileInputStream(boolean atStart) throws IOException {
86     if (!isLocked())
87       return null;
88     if (atStart)
89       rafile.seek(0);
90     return new FileInputStream(rafile.getFD());
91   }
92
93   /**
94    * gets Locked stream to write to
95    * FileInput always starts at the *end* of the file (after any truncation)
96    * @param clear true means file will be cleared to zero length
97    * @return null if file is not locked
98    * @throws IOException
99    */
100   public FileOutputStream getFileOutputStream(boolean clear) throws IOException {
101     if (!isLocked())
102       return null;
103     if (clear)
104       rafile.setLength(0);
105     rafile.seek(rafile.length());
106     return new LockedFileOutputStream(rafile.getFD());
107   }
108
109   /**
110    * return buffered output stream to locked file.
111    * @param clear - true means file is truncated to 0 length before writing 
112    * @return
113    */
114   public BufferedOutputStream getBufferedOutputStream(boolean clear) throws IOException {
115     FileOutputStream fos = getFileOutputStream(clear);
116     if (fos!=null)
117       return new BufferedOutputStream(fos);
118     return null;
119   }
120   /**
121    * @see org.vamsas.client.simpleclient.Lock#finalize()
122    */
123   protected void finalize() throws Throwable {
124     release(true); // we explicitly lose the lock here.
125     // log.debug("lock closing through garbage collection ?");
126     super.finalize();
127   }
128
129 }