package org.vamsas.client.simpleclient; import java.io.File; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; 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=extantlock; return lockFile(); } /** * Get a lock for the SessionFile * * @return true if lock was made */ protected boolean lockFile() { if (fileLock != null) if (fileLock.isLocked()) return true; else // lock failed for some reason. fileLock.release(); fileLock = null; if (sessionFile != null) { if (sessionFile.exists()) { // TODO: see if we need to loop-wait for locks or they just block until // lock is made... do { if (fileLock!=null) fileLock.release(); fileLock = new Lock(sessionFile); // TODO: wait around if we can't get the lock. } while (!fileLock.isLocked()); // fileLock = new Lock(sessionFile); return fileLock.isLocked(); } } else log.error("lockFile called for non-initialised SessionFile!"); // no lock possible return false; } /** * 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(null, 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); FileOutputStream tos = new FileOutputStream(tempfile); tos.getChannel().transferFrom(fileLock.rafile.getChannel(), 0, fileLock.rafile.length()); tos.close(); } 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."); lockFile(extantLock); newData.lockFile(); fileLock.rafile.getChannel().transferFrom(newData.fileLock.rafile.getChannel(), 0, newData.fileLock.rafile.length()); } }