/*
* This file is part of the Vamsas Client version 0.2.
* Copyright 2010 by Jim Procter, Iain Milne, Pierre Marguerite,
* Andrew Waterhouse and Dominik Lindner.
*
* Earlier versions have also been incorporated into Jalview version 2.4
* since 2008, and TOPALi version 2 since 2007.
*
* The Vamsas Client is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* The Vamsas Client is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with the Vamsas Client. If not, see .
*/
package uk.ac.vamsas.client.simpleclient;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.URL;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import uk.ac.vamsas.client.SessionHandle;
import uk.ac.vamsas.client.simpleclient.SimpleSessionHandle;
/**
* @author Pierre MARGUERITE
*
*
*/
public class SessionsFile extends ListFile {
private static Log log = LogFactory.getLog(SessionsFile.class);
/**
* when set true - get FileNotFoundExceptions on WinXP when writing to locked
* stream after the backup has been made (via the backupFile method)
*/
boolean backup = false;
/**
* number of my session in list - passed back when a session is added to list,
* and used (if valid) for quickly looking up presence of session handle in
* the list.
*/
private int syncnum = 1;
/**
* @param file
*/
public SessionsFile(File file) throws java.io.IOException {
super(file);
}
/**
* internal method for getting sessionsList - ensures a lock has been made but
* does not release it.
*
* @return list of clients
*/
private SimpleSessionHandle[] retrieveSessionHandles() {
if (lockFile()) {
try {
SimpleSessionHandle[] sessions = null;
if (this.fileLock.length() > 0) {
ObjectInputStream is = new ObjectInputStream(this.fileLock
.getBufferedInputStream(true));
Object o;
o = is.readObject();
if (o != null) {
try {
if (o instanceof SimpleSessionHandle[]) {
sessions = (SimpleSessionHandle[]) o;
} else {
// legacy support or incorrect path.
if (o instanceof SessionHandle[]) {
log.info("Importing VAMSAS 0.1 clientHandle list.");
SessionHandle[] oldsess = (SessionHandle[]) o;
File sessdir;
sessions = new SimpleSessionHandle[oldsess.length];
for (int s=0;s sessions.length)
|| !session.equals(sessions[this.syncnum - 1])) {
for (int i = 0, j = sessions.length; i < j; i++) {
if (sessions[i].equals(session)) {
mynum = i;
break;
}
}
} else {
mynum = this.syncnum - 1;
}
if (mynum > -1) {
SimpleSessionHandle[] newlist = new SimpleSessionHandle[sessions.length - 1];
for (int k = 0, i = 0, j = sessions.length; i < j; i++)
if (i != mynum)
newlist[k++] = sessions[i];
if (!putSessionsList(newlist))
throw new Error("Failed to write new sessionsList!"); // failed to
// put the
// sessionList
// to disk.
}
}
unlockFile();
} else {
throw new Error(
"Couldn't get lock for "
+ ((this.sessionFile == null) ? "Unitialised sessionFile in SessionsFile"
: this.sessionFile.getAbsolutePath()));
}
}
/**
* Adds a SessionHandle to the SessionList file - optionally disambiguating
* the SessionHandle (modifes the URN). Note: Caller is left to release the
* lock on the SessionList.
*
* @param session
* @param disambiguate
* - flag indicating if the URN for me should be disambiguated to
* differentiate between sessions.
* @return index of sessionHandle in new list, or -1-position of existing
* sessionHandle (if disambiguate is true)
*/
protected int addSession(SimpleSessionHandle session, boolean disambiguate) {
int newsession = 0;
int tries = 5;
while (tries-- > 0 && !lockFile())
try {
Thread.sleep(1);
} catch (Exception e) {
}
;
if (lockFile()) {
SimpleSessionHandle[] sessions = retrieveSessionHandles();
if (sessions == null) {
sessions = new SimpleSessionHandle[1];
sessions[0] = session;
newsession = 1;
} else {
int k = 0;
for (int i = 0, j = sessions.length; i < j; i++) {
if (sessions[i].equals(session)) {
if (disambiguate) {
while (sessions[i].equals(session)) {
// me.setClientUrn(me.getClientUrn() + k++); // TODO: make a
// better
// disambiguation of
// urn.
}
} else {
// will not write the ambiguous clientHandle to disk, just return
// its index.
return -1 - i;
}
}
}
int i, j;
SimpleSessionHandle[] newlist = new SimpleSessionHandle[sessions.length + 1];
for (i = 0, j = sessions.length; i < j; i++)
newlist[i] = sessions[i];
newlist[j] = session;
sessions = newlist;
newsession = j + 1;
}
if (!putSessionsList(sessions))
return 0; // failed to put the clientList to disk.
}
return newsession;
}
/**
* safely writes sessions array to the file referred to by sessionFile.
*
* @param clients
* @return true if successful write. Throws Errors otherwise.
*/
protected boolean putSessionsList(SimpleSessionHandle[] clients) {
if (lockFile()) {
File templist = null;
if (!this.backup || (templist = backupSessionFile()) != null) {
int retries = 3;
while (retries-- > 0) {
try {
ObjectOutputStream os = new ObjectOutputStream(this.fileLock
.getBufferedOutputStream(true));
log.debug("About to write " + clients.length
+ " sessionHandles to output stream.");
os.writeObject(clients);
// os.flush();
os.close();
// All done - remove the backup.
if (this.backup)
templist.delete();
templist = null;
retries = -1;
} catch (Exception e) {
// System.err
// .println("Serious - problems writing to sessionFile.");
log.error("Serious - problems writing to sessionFile.", e);
if (retries > 0 && templist != null) {
// System.err.println("Recovering from Backup in "
// + templist.getAbsolutePath());
log.error("Recovering from Backup in "
+ templist.getAbsolutePath());
templist.renameTo(this.fileLock.target);
}
// e.printStackTrace(System.err);
log.error(e);
}
}
if (retries > -2) {
// System.err
// .println("Serious - problems writing to sessionFile. Giving Up.");
log.error("Serious - problems writing to sessionFile. Giving Up.");
return false;
}
} else {
throw new Error(
"Couldn't create backup of the clientList before writing to it!");
}
} else {
throw new Error("Could not lock the clientList: "
+ ((this.sessionFile == null) ? "Unitialized ClientsFile"
: " failed to get lock on " + this.sessionFile.getAbsolutePath()));
}
// successful!
return true;
}
public void clearList() {
if (lockFile()) {
try {
FileOutputStream fout = this.fileLock.getFileOutputStream(true);
fout.flush();
fout.close();
} catch (Exception e) {
throw new Error("Problems trying to clear clientlist!", e);
}
}
}
}