0ff306eb3d5421fed281720ea29e83ba9cfb72d8
[vamsas.git] / src / org / vamsas / client / simpleclient / SessionFile.java
1 package org.vamsas.client.simpleclient;
2
3 import java.io.File;
4 import java.io.FileNotFoundException;
5 import java.io.FileOutputStream;
6 import java.io.IOException;
7
8 import org.apache.commons.logging.Log;
9 import org.apache.commons.logging.LogFactory;
10
11 /**
12  * Basic methods for classes handling locked IO on files 
13  * monitored by all (simpleclient) clients in a vamsas session.
14  * @author jimp
15  *TODO: support non nio file locking capable systems
16  */
17 public class SessionFile {
18   private static Log log = LogFactory.getLog(SessionFile.class);
19   protected File sessionFile;
20   protected Lock fileLock = null;
21
22   protected SessionFile(File file) {
23     super();
24     sessionFile = file;
25   }
26
27   protected boolean lockFile(Lock extantlock) {
28     if (fileLock!=null && !fileLock.isLocked()) {
29       fileLock.release();// tidy up invalid lock
30     }
31     fileLock=extantlock;
32     return lockFile();
33   }
34
35   /**
36    * Get a lock for the SessionFile
37    * 
38    * @return true if lock was made
39    */
40   protected boolean lockFile() {
41     if (fileLock != null)
42       if (fileLock.isLocked())
43         return true;
44       else 
45         // lock failed for some reason.
46         fileLock.release();
47     fileLock = null;
48     if (sessionFile != null) {
49       if (sessionFile.exists()) {
50         // TODO: see if we need to loop-wait for locks or they just block until
51         // lock is made...
52         do {
53           if (fileLock!=null)
54             fileLock.release();
55           fileLock = new Lock(sessionFile); // TODO: wait around if we can't get the lock.
56         } while (!fileLock.isLocked());
57         // fileLock = new Lock(sessionFile);
58         return fileLock.isLocked();
59       }
60     } else
61       log.error("lockFile called for non-initialised SessionFile!");
62   
63     // no lock possible
64     return false;
65   }
66
67   /**
68    * Explicitly release the SessionFile's lock.
69    * 
70    * @return true if lock was released.
71    */
72   protected void unlockFile() {
73     if (fileLock != null) {
74       fileLock.release();    
75       fileLock = null;
76     }
77   }
78
79   /**
80    * Makes a backup of the sessionFile.
81    * @return Backed up SessionFile or null if failed to make backup.
82    */
83   protected File backupSessionFile() {
84     return backupSessionFile(null, sessionFile.getName(),".old", sessionFile.getParentFile());
85   }
86
87   protected File backupSessionFile(Lock extantLock, String backupPrefix, String backupSuffix, File backupDir) {
88     File tempfile=null;
89     if (lockFile(extantLock)) {
90       try {
91         tempfile = File.createTempFile(backupPrefix, backupSuffix, backupDir);
92         FileOutputStream tos = new FileOutputStream(tempfile);
93         tos.getChannel().transferFrom(fileLock.rafile.getChannel(), 0,
94             fileLock.rafile.length());
95         tos.close();
96       } catch (FileNotFoundException e1) {
97         log.warn("Can't create temp file for "+sessionFile.getName(),e1);
98         tempfile=null;
99       } catch (IOException e1) {
100         log.warn("Error when copying content to temp file for "+sessionFile.getName(),e1);
101         tempfile=null;
102       }
103     }
104     return tempfile;
105   }
106   /**
107    * Replaces data in sessionFile with data from file handled by another sessionFile
108    * passes up any exceptions.
109    * @param newData source for new data
110    */
111   protected void updateFrom(Lock extantLock, SessionFile newData) throws IOException {
112     log.debug("Updating "+sessionFile.getAbsolutePath()+" from "+newData.sessionFile.getAbsolutePath());
113     if (newData==null)
114       throw new IOException("Null newData object.");
115     if (newData.sessionFile==null)
116       throw new IOException("Null SessionFile in newData.");
117       
118     lockFile(extantLock);  
119     newData.lockFile();
120     fileLock.rafile.getChannel().transferFrom(newData.fileLock.rafile.getChannel(), 0, 
121         newData.fileLock.rafile.length());
122   }
123   /**
124    * remove all trace of the sessionFile file
125    *
126    */
127   protected void eraseExistence() {
128     unlockFile();
129     if (sessionFile!=null) {
130       sessionFile.delete();
131       sessionFile = null;
132     }
133   }
134 }