-package uk.ac.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.ReadableByteChannel;
-
-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=null;
- }
- if (extantlock!=null && extantlock.isLocked())
- fileLock=extantlock; // THIS IS BROKEN - lockFile then nulls the lock.
- return lockFile();
- }
- private boolean ensureSessionFile() {
- if (sessionFile != null) {
- if (!sessionFile.exists()) {
- // create new file
- try {
- if (!sessionFile.createNewFile()) {
- log.error("Failed to create file prior to locking: "+sessionFile);
- return false;
- }
- } catch (IOException e) {
- log.error("Exception when trying to create file "+sessionFile, e);
- return false;
- }
- }
- return true;
- }
- log.error("ensureSessionFile called for non-initialised SessionFile!");
- return false;
- }
- /**
- * Get a lock for the SessionFile
- *
- * @return true if lock was made
- */
- protected boolean lockFile() {
- if (fileLock != null) {
- if (fileLock.isLocked()) {
- if (!ensureSessionFile())
- return false;
- return true;
- } else {
- // lock failed for some reason.
- fileLock.release();
- log.info("Unexpected session file lock failure. Trying to get it again.");
- fileLock=null;
- }
- }
- if (!ensureSessionFile())
- return false;
- // TODO: see if we need to loop-wait for locks or they just block until
- // lock is made...
- long tries=5000;
- do {
- tries--;
- if (fileLock==null || !fileLock.isLocked()) {
- //try { Thread.sleep(1); } catch (Exception e) {};
- fileLock = LockFactory.getLock(sessionFile,true); // TODO: wait around if we can't get the lock.
- }
- } while (tries>0 && !fileLock.isLocked());
- if (!fileLock.isLocked())
- log.error("Failed to get lock for "+sessionFile);
- // fileLock = new Lock(sessionFile);
- return fileLock.isLocked();
- }
-
- /**
- * 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(fileLock, 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);
- long sourceln = fileLock.length();
- if (sourceln>0) {
- FileOutputStream tos = new FileOutputStream(tempfile);
- ReadableByteChannel channel;
- channel = fileLock.getRaChannel().position(0);
- long ntrans = 0;
- while (ntrans<sourceln)
- {
- long tlen;
- ntrans+= tlen = tos.getChannel().transferFrom(channel, ntrans,
- sourceln);
- if (log.isDebugEnabled())
- {
- log.debug
- ("Transferred "+tlen+" out of "+sourceln+" bytes");
- }
- }
- tos.close();
- if (!channel.isOpen())
- throw new Error("LIBRARY PORTABILITY ISSUE: "+tos.getChannel().getClass()+".transferFrom closes source channel!");
- if (!lockFile(extantLock))
- throw new Error("LIBRARY PORTABILITY ISSUE: Lost lock for "+sessionFile.getName()+" after backup.");
-
- }
- } 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.");
-
- if (!lockFile(extantLock))
- throw new IOException("Failed to get write lock for "+sessionFile);
- if (!newData.lockFile())
- throw new IOException("Failed to get lock for updateFrom "+newData.sessionFile);
- RandomAccessFile nrafile = newData.fileLock.getRaFile();
- nrafile.seek(0);
- RandomAccessFile trafile = fileLock.getRaFile();
- /*long tries=5000;
- while (trafile==null && --tries>0) {
- log.debug("Lost lock on "+sessionFile+"! Re-trying for a transfer.");
- lockFile();
- trafile = fileLock.getRaFile();
- }*/
- // TODO JBPNote: attempt to ensure save really saves the VamDoc.jar file
- trafile.seek(0);
- trafile.getChannel().transferFrom(nrafile.getChannel(), 0,
- nrafile.length());
- // JBPNote: attempt to close the streams to flush the data out
- // trafile.close();
- //nrafile.close();
- }
- /**
- * remove all trace of the sessionFile file
- *
- */
- protected void eraseExistence() {
- unlockFile();
- if (sessionFile!=null) {
- sessionFile.delete();
- sessionFile = null;
- }
- }
- /* (non-Javadoc)
- * @see uk.ac.vamsas.client.simpleclient.Lock#getBufferedInputStream(boolean)
- */
- public BufferedInputStream getBufferedInputStream(boolean atStart) throws IOException {
- lockFile();
- return fileLock.getBufferedInputStream(atStart);
- }
-
- /* (non-Javadoc)
- * @see uk.ac.vamsas.client.simpleclient.Lock#getBufferedOutputStream(boolean)
- */
- public BufferedOutputStream getBufferedOutputStream(boolean clear) throws IOException {
- lockFile();
- return fileLock.getBufferedOutputStream(clear);
- }
-
- /* (non-Javadoc)
- * @see uk.ac.vamsas.client.simpleclient.Lock#getFileInputStream(boolean)
- */
- public FileInputStream getFileInputStream(boolean atStart) throws IOException {
- lockFile();
- return fileLock.getFileInputStream(atStart);
- }
-
- /* (non-Javadoc)
- * @see uk.ac.vamsas.client.simpleclient.Lock#getFileOutputStream(boolean)
- */
- public FileOutputStream getFileOutputStream(boolean clear) throws IOException {
- lockFile();
- return fileLock.getFileOutputStream(clear);
- }
-
-}
+/*\r
+ * This file is part of the Vamsas Client version 0.1. \r
+ * Copyright 2009 by Jim Procter, Iain Milne, Pierre Marguerite, \r
+ * Andrew Waterhouse and Dominik Lindner.\r
+ * \r
+ * Earlier versions have also been incorporated into Jalview version 2.4 \r
+ * since 2008, and TOPALi version 2 since 2007.\r
+ * \r
+ * The Vamsas Client is free software: you can redistribute it and/or modify\r
+ * it under the terms of the GNU Lesser General Public License as published by\r
+ * the Free Software Foundation, either version 3 of the License, or\r
+ * (at your option) any later version.\r
+ * \r
+ * The Vamsas Client is distributed in the hope that it will be useful,\r
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ * GNU Lesser General Public License for more details.\r
+ * \r
+ * You should have received a copy of the GNU Lesser General Public License\r
+ * along with the Vamsas Client. If not, see <http://www.gnu.org/licenses/>.\r
+ */\r
+package uk.ac.vamsas.client.simpleclient;\r
+\r
+import java.io.BufferedInputStream;\r
+import java.io.BufferedOutputStream;\r
+import java.io.File;\r
+import java.io.FileInputStream;\r
+import java.io.FileNotFoundException;\r
+import java.io.FileOutputStream;\r
+import java.io.IOException;\r
+import java.io.RandomAccessFile;\r
+import java.nio.channels.ReadableByteChannel;\r
+\r
+import org.apache.commons.logging.Log;\r
+import org.apache.commons.logging.LogFactory;\r
+\r
+/**\r
+ * Basic methods for classes handling locked IO on files monitored by all\r
+ * (simpleclient) clients in a vamsas session.\r
+ * \r
+ * @author jimp TODO: support non nio file locking capable systems\r
+ */\r
+public class SessionFile {\r
+ private static Log log = LogFactory.getLog(SessionFile.class);\r
+\r
+ protected File sessionFile;\r
+\r
+ protected Lock fileLock = null;\r
+\r
+ protected SessionFile(File file) {\r
+ super();\r
+ sessionFile = file;\r
+ }\r
+\r
+ protected boolean lockFile(Lock extantlock) {\r
+ if (fileLock != null && !fileLock.isLocked()) {\r
+ fileLock.release();// tidy up invalid lock\r
+ fileLock = null;\r
+ }\r
+ if (extantlock != null && extantlock.isLocked())\r
+ fileLock = extantlock; // THIS IS BROKEN - lockFile then nulls the lock.\r
+ return lockFile();\r
+ }\r
+\r
+ private boolean ensureSessionFile() {\r
+ if (sessionFile != null) {\r
+ if (!sessionFile.exists()) {\r
+ // create new file\r
+ try {\r
+ if (!sessionFile.createNewFile()) {\r
+ log.error("Failed to create file prior to locking: " + sessionFile);\r
+ return false;\r
+ }\r
+ } catch (IOException e) {\r
+ log.error("Exception when trying to create file " + sessionFile, e);\r
+ return false;\r
+ }\r
+ }\r
+ return true;\r
+ }\r
+ log.error("ensureSessionFile called for non-initialised SessionFile!");\r
+ return false;\r
+ }\r
+\r
+ /**\r
+ * Get a lock for the SessionFile\r
+ * \r
+ * @return true if lock was made\r
+ */\r
+ protected boolean lockFile() {\r
+ if (fileLock != null) {\r
+ if (fileLock.isLocked()) {\r
+ if (!ensureSessionFile())\r
+ return false;\r
+ return true;\r
+ } else {\r
+ // lock failed for some reason.\r
+ fileLock.release();\r
+ log\r
+ .info("Unexpected session file lock failure. Trying to get it again.");\r
+ fileLock = null;\r
+ }\r
+ }\r
+ if (!ensureSessionFile())\r
+ return false;\r
+ // TODO: see if we need to loop-wait for locks or they just block until\r
+ // lock is made...\r
+ long tries = 5000;\r
+ do {\r
+ tries--;\r
+ if (fileLock == null || !fileLock.isLocked()) {\r
+ // try { Thread.sleep(1); } catch (Exception e) {};\r
+ fileLock = LockFactory.getLock(sessionFile, true); // TODO: wait around\r
+ // if we can't get\r
+ // the lock.\r
+ }\r
+ } while (tries > 0 && !fileLock.isLocked());\r
+ if (!fileLock.isLocked())\r
+ log.error("Failed to get lock for " + sessionFile);\r
+ // fileLock = new Lock(sessionFile);\r
+ return fileLock.isLocked();\r
+ }\r
+\r
+ /**\r
+ * Explicitly release the SessionFile's lock.\r
+ * \r
+ * @return true if lock was released.\r
+ */\r
+ protected void unlockFile() {\r
+ if (fileLock != null) {\r
+ fileLock.release();\r
+ fileLock = null;\r
+ }\r
+ }\r
+\r
+ /**\r
+ * Makes a backup of the sessionFile.\r
+ * \r
+ * @return Backed up SessionFile or null if failed to make backup.\r
+ */\r
+ protected File backupSessionFile() {\r
+ return backupSessionFile(fileLock, sessionFile.getName(), ".old",\r
+ sessionFile.getParentFile());\r
+ }\r
+\r
+ protected File backupSessionFile(Lock extantLock, String backupPrefix,\r
+ String backupSuffix, File backupDir) {\r
+ File tempfile = null;\r
+ if (lockFile(extantLock)) {\r
+ try {\r
+ tempfile = File.createTempFile(backupPrefix, backupSuffix, backupDir);\r
+ long sourceln = fileLock.length();\r
+ if (sourceln > 0) {\r
+ FileOutputStream tos = new FileOutputStream(tempfile);\r
+ ReadableByteChannel channel;\r
+ channel = fileLock.getRaChannel().position(0);\r
+ long ntrans = 0;\r
+ while (ntrans < sourceln) {\r
+ long tlen;\r
+ ntrans += tlen = tos.getChannel().transferFrom(channel, ntrans,\r
+ sourceln);\r
+ if (log.isDebugEnabled()) {\r
+ log.debug("Transferred " + tlen + " out of " + sourceln\r
+ + " bytes");\r
+ }\r
+ }\r
+ tos.close();\r
+ if (!channel.isOpen())\r
+ throw new Error("LIBRARY PORTABILITY ISSUE: "\r
+ + tos.getChannel().getClass()\r
+ + ".transferFrom closes source channel!");\r
+ if (!lockFile(extantLock))\r
+ throw new Error("LIBRARY PORTABILITY ISSUE: Lost lock for "\r
+ + sessionFile.getName() + " after backup.");\r
+\r
+ }\r
+ } catch (FileNotFoundException e1) {\r
+ log.warn("Can't create temp file for " + sessionFile.getName(), e1);\r
+ tempfile = null;\r
+ } catch (IOException e1) {\r
+ log.warn("Error when copying content to temp file for "\r
+ + sessionFile.getName(), e1);\r
+ tempfile = null;\r
+ }\r
+ }\r
+ return tempfile;\r
+ }\r
+\r
+ /**\r
+ * Replaces data in sessionFile with data from file handled by another\r
+ * sessionFile passes up any exceptions.\r
+ * \r
+ * @param newData\r
+ * source for new data\r
+ */\r
+ protected void updateFrom(Lock extantLock, SessionFile newData)\r
+ throws IOException {\r
+ log.debug("Updating " + sessionFile.getAbsolutePath() + " from "\r
+ + newData.sessionFile.getAbsolutePath());\r
+ if (newData == null)\r
+ throw new IOException("Null newData object.");\r
+ if (newData.sessionFile == null)\r
+ throw new IOException("Null SessionFile in newData.");\r
+\r
+ if (!lockFile(extantLock))\r
+ throw new IOException("Failed to get write lock for " + sessionFile);\r
+ if (!newData.lockFile())\r
+ throw new IOException("Failed to get lock for updateFrom "\r
+ + newData.sessionFile);\r
+ RandomAccessFile nrafile = newData.fileLock.getRaFile();\r
+ nrafile.seek(0);\r
+ RandomAccessFile trafile = fileLock.getRaFile();\r
+ /*\r
+ * long tries=5000; while (trafile==null && --tries>0) {\r
+ * log.debug("Lost lock on "+sessionFile+"! Re-trying for a transfer.");\r
+ * lockFile(); trafile = fileLock.getRaFile(); }\r
+ */\r
+ // TODO JBPNote: attempt to ensure save really saves the VamDoc.jar file\r
+ trafile.seek(0);\r
+ trafile.getChannel()\r
+ .transferFrom(nrafile.getChannel(), 0, nrafile.length());\r
+ // JBPNote: attempt to close the streams to flush the data out\r
+ // trafile.close();\r
+ // nrafile.close();\r
+ }\r
+\r
+ /**\r
+ * remove all trace of the sessionFile file\r
+ * \r
+ */\r
+ protected void eraseExistence() {\r
+ unlockFile();\r
+ if (sessionFile != null) {\r
+ sessionFile.delete();\r
+ sessionFile = null;\r
+ }\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
+ * @see uk.ac.vamsas.client.simpleclient.Lock#getBufferedInputStream(boolean)\r
+ */\r
+ public BufferedInputStream getBufferedInputStream(boolean atStart)\r
+ throws IOException {\r
+ lockFile();\r
+ return fileLock.getBufferedInputStream(atStart);\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
+ * @see uk.ac.vamsas.client.simpleclient.Lock#getBufferedOutputStream(boolean)\r
+ */\r
+ public BufferedOutputStream getBufferedOutputStream(boolean clear)\r
+ throws IOException {\r
+ lockFile();\r
+ return fileLock.getBufferedOutputStream(clear);\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
+ * @see uk.ac.vamsas.client.simpleclient.Lock#getFileInputStream(boolean)\r
+ */\r
+ public FileInputStream getFileInputStream(boolean atStart) throws IOException {\r
+ lockFile();\r
+ return fileLock.getFileInputStream(atStart);\r
+ }\r
+\r
+ /*\r
+ * (non-Javadoc)\r
+ * \r
+ * @see uk.ac.vamsas.client.simpleclient.Lock#getFileOutputStream(boolean)\r
+ */\r
+ public FileOutputStream getFileOutputStream(boolean clear) throws IOException {\r
+ lockFile();\r
+ return fileLock.getFileOutputStream(clear);\r
+ }\r
+\r
+}\r