--- /dev/null
+/* EMBL - The European Bioinformatics institute
+* MSD Group
+* VAMSAS Project
+*
+* Copyright (c) 2005-2006 Thr European Bioinformatics Institute. All rights reserved.
+*
+* Redistribution and use in source and binary forms, with or without
+* modification, are permitted provided that the following conditions
+* are met:
+*
+* 1. Redistributions of source code must retain the above copyright
+* notice, this list of conditions and the following disclaimer.
+*
+* 2. Redistributions in binary form must reproduce the above copyright
+* notice, this list of conditions and the following disclaimer in
+* the documentation and/or other materials provided with the
+* distribution.
+*
+* 3. The name MSD must not be used to endorse or promote products
+* derived from this software without prior written permission. For
+* written permission, please contact msd-help@ebi.ac.uk
+*
+* 4. Products derived from this software may not be called "MSD"
+* nor may "MSD" appear in their names without prior written
+* permission of the MSD developers.
+*
+* 5. Redistributions of any form whatsoever must retain the following
+* acknowledgment:
+* "This product includes software developed by MSD
+* (http://www.ebi.ac.uk/)"
+*
+* THIS SOFTWARE IS PROVIDED BY THE MSD GROUP ``AS IS'' AND ANY
+* EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE ENSEMBL GROUP OR
+* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+* OF THE POSSIBILITY OF SUCH DAMAGE.
+*
+* The European Bioinformatics Institute may publish revised and/or new
+* versions of this license with new releases of VAMSAS software.
+*==============================================================================
+*
+* @author <a href="mailto:pierre@ebi.ac.uk">Pierre MARGUERITE</a>
+*
+* Dec 13, 2006 - VamsasClientV4
+*
+*/
+
+package org.vamsas.client.simpleclient;
+
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.vamsas.client.SessionHandle;
+
+/**
+ * @author <a href="mailto:pierre@ebi.ac.uk">Pierre MARGUERITE</a>
+ *
+ *
+ */
+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 SessionHandle[] retrieveSessionHandles() {
+ if (lockFile()) {
+ try {
+ SessionHandle[] clients=null;
+ if (this.fileLock.length()>0) {
+
+ ObjectInputStream is = new ObjectInputStream(this.fileLock.getBufferedInputStream(true));
+ Object o;
+ o=is.readObject();
+ if (o!=null) {
+ try {
+ clients = (SessionHandle[]) o;
+ }
+ catch (Exception e) {
+ log.error("Garbage in the clientHandle list "+this.sessionFile,e);
+ }
+ }
+ }
+ return clients;
+ } catch (FileNotFoundException e) {
+ // e.printStackTrace(System.err);
+ log.error(e);
+ } catch (Exception e) {
+ log.error(e);
+ //e.printStackTrace(System.err);
+ }
+ }
+ return null;
+ }
+
+ /**
+ * get the SessionsList from the file. May return null if lock failed!
+ * @return sessionsList
+ */
+ public SessionHandle[] retrieveSessionsList() {
+ if (lockFile()) {
+ SessionHandle[] clients = retrieveSessionHandles();
+ unlockFile();
+ return clients;
+ }
+ return null;
+ }
+
+ /**
+ * get list from the locked ClientList.
+ * @param extantlock
+ * @return clientList or null if lock failed (or file was empty)
+ */
+ public SessionHandle[] retrieveSessionsList(Lock extantlock) {
+ if (lockFile(extantlock)) {
+ SessionHandle[] clients = retrieveSessionHandles();
+ unlockFile();
+ return clients;
+ }
+ return null;
+ }
+
+
+ /**
+ * adds clientHandle me to the clientList under an existing lock extantLock.
+ * @param me
+ * @param extantLock
+ * @return client index in list or 0 if lock was invalid or addClient operation failed.
+ */
+ public int addSession(SessionHandle me, Lock extantLock) {
+ return addSession(me, true, extantLock);
+ }
+
+ /**
+ * adds SessionsHandle me to the sessionsList under an existing lock.
+ * @param me - sessionsHandle
+ * @param disambig - if true then add will fail if an identical clientHandle already exists
+ * @param extantLock - existing lock
+ * @return client index in list or 0 if addClient (or the lock) failed.
+ */
+
+ public int addSession(SessionHandle session, boolean disambig, Lock extantLock) {
+ if (lockFile(extantLock)) {
+ this.syncnum = addSession(session, disambig);
+ unlockFile();
+ return this.syncnum;
+ }
+ return 0;
+ }
+
+ /**
+ * removes the current session from the SessionsList without complaint if the session isn't in the sessionsList already.
+ * @param me client handle to be removed
+ * @param clientlock existing lock passed from watcher.
+ */
+ public void removeSession(SessionHandle session, Lock clientlock) {
+ int mynum =-1;
+ if (lockFile(clientlock)) {
+ SessionHandle[] sessions = retrieveSessionHandles();
+ if (sessions != null) {
+ if ((this.syncnum<=0 || this.syncnum>sessions.length) || sessions[this.syncnum-1]!=session) {
+ 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) {
+ SessionHandle[] newlist = new SessionHandle[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 "+((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 me
+ * @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(SessionHandle session, boolean disambiguate) {
+ int newsession = 0;
+ int tries=5;
+ while (tries-->0 && !lockFile())
+ try { Thread.sleep(1); } catch (Exception e){};
+ if (lockFile()) {
+ SessionHandle[] sessions = retrieveSessionHandles();
+
+ if (sessions == null) {
+ sessions = new SessionHandle[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;
+ SessionHandle[] newlist = new SessionHandle[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(SessionHandle[] 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.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);
+
+ }
+ }
+
+ }
+}
+/*
+* VAMSAS Project
+*
+
+*
+* Dec 13, 2006
+*
+*/
+
package org.vamsas.client.simpleclient;
import java.io.File;
+
import java.io.IOException;
+
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.vamsas.client.ClientHandle;
import org.vamsas.client.IClient;
import org.vamsas.client.IClientFactory;
+import org.vamsas.client.InvalidSessionUrnException;
import org.vamsas.client.NoDefaultSessionException;
+import org.vamsas.client.SessionHandle;
import org.vamsas.client.UserHandle;
/**
- * TODO document type SimpleClientFactory
- * @author jimp
- *
+ *
+ *
*/
public class SimpleClientFactory implements IClientFactory {
+
private static Log log = LogFactory.getLog(SimpleClientFactory.class);
- File sessionArena;
+ private File sessionArena = null;
+
+ private String vamsasSubdirectoryName = ".vamsas";
+
+ private SessionsFile sessionFile = null;
+ private static final String SESSION_LIST="sessions.obj";
+
+ //private String[] currentlyAvailableDessions = null;
/**
* default constructor - called by CreateClientFactory only.
*
+ *Inits the sessionarena to the directory .vamsas of the user home directory.
+ *
*/
- public SimpleClientFactory() {
- sessionArena = null;
+ public SimpleClientFactory() throws IOException
+ {
+ // sessionArena
+
+ //retrieves user home directory
+ String userHomeDirectory = System.getProperty("user.home");
+ if (userHomeDirectory == null || userHomeDirectory.length()<1)
+ {
+ new IOException("Unable to detect user home directory");
+ }
+ String sessionArenaPath = userHomeDirectory.concat(File.separator.concat(this.vamsasSubdirectoryName));
+
+ this.initSessionArena(sessionArenaPath);
+ this.initFactoryObjects();
}
+
+
/**
* Create a client factory that works with sessions at the given
* path.
- * @param path
+ * @param path path to directory called session arena, where will be created session directories and session files.
*/
- public SimpleClientFactory(String path) throws IOException {
+ public SimpleClientFactory(String path) throws IOException
+ {
+ this.initSessionArena(path);
+ }
+ /**
+ * Inits sessionArena to a given path.
+ * checks if path is valid.
+ *
+ * @param path path to a directory to use
+ * @throws IOException if the path is incorrect
+ */
+ private void initSessionArena (String path) throws IOException
+ {
// Check path is valid and read/writeable.
- File newarena = new File(path);
- if (newarena.isDirectory() && newarena.canRead() && newarena.canWrite()) {
- sessionArena = newarena;
- } else {
- sessionArena = null;
- throw(new IOException("Cannot read and write to a directory called "+path));
+ File arenaFile = new File (path);
+ if (!arenaFile.exists())
+ {
+ if (! arenaFile.mkdirs())
+ {
+ this.sessionArena = null;
+ throw(new IOException("Unable to create a directory called "+path));
+ }
}
+ if (arenaFile.exists() && arenaFile.isDirectory() && arenaFile.canRead() && arenaFile.canWrite())
+ {
+ this.sessionArena = arenaFile;
+ }
+ else
+ {
+ this.sessionArena = null;
+ throw(new IOException("Cannot read and write to a directory called "+path));
+ }
}
- /* (non-Javadoc)
+ /**
+ * construct SessionFile objects and watchers for each
+ */
+ private void initFactoryObjects() throws IOException {
+ if (this.sessionFile!=null )
+ throw new IOException("initFactoryObjects called for initialised ClientFactory object.");
+ this.sessionFile = new SessionsFile(new File(this.sessionArena,SESSION_LIST));
+
+ }
+ /**
* @see org.vamsas.client.IClientFactory#getCurrentSessions()
*/
- public String[] getCurrentSessions() {
- // TODO look in the arena and enumerate session handles for return.
- return new String[] {};
+ public String[] getCurrentSessions()
+ {
+ String[] sessions = null;
+ if (this.sessionFile!=null )
+ {
+ SessionHandle[] sessionHandles = this.sessionFile.retrieveSessionsList();
+ if (sessionHandles != null)
+ {
+ sessions = new String[sessionHandles.length];
+ for (int i = sessionHandles.length -1; i > 0; i--)
+ {
+ SessionHandle sessionHandle = sessionHandles[i];
+ sessions [i] = sessionHandle.getSessionUrn();
+ }
+ }
+ }
+ return sessions;
}
- /* (non-Javadoc)
+
+
+ private void discoverSession()
+ {
+
+ }
+
+ /**
* @see org.vamsas.client.IClientFactory#getIClient(org.vamsas.client.ClientHandle)
+ *
+ * Creates a IClient object, using default UserHandle with system variables:"user.name" or "USERNAME")),
+ "host.name" or "HOSTNAME"
*/
- public IClient getIClient(ClientHandle applicationHandle) throws NoDefaultSessionException {
- // create a new session
- // register new ClientHandle in session
- // create SimpleClient instance
- return null;
+ public IClient getIClient(ClientHandle applicationHandle)
+ throws NoDefaultSessionException {
+
+ return this.getIClient(applicationHandle, (UserHandle) null);
}
- /* (non-Javadoc)
+ /**
* @see org.vamsas.client.IClientFactory#getIClient(org.vamsas.client.ClientHandle, java.lang.String)
*/
public IClient getIClient(ClientHandle applicationHandle, String sessionUrn) {
- // locate session from Urn
- // check that clientHandle is unique (with default user) - if not update the clientHandle urn to make it unique.
- // wait for lock and attach to session
- // create SimpleClient instance
+ // TODO Auto-generated method stub
return null;
}
- /* (non-Javadoc)
+ /**
* @see org.vamsas.client.IClientFactory#getIClient(org.vamsas.client.ClientHandle, org.vamsas.client.UserHandle, java.lang.String)
*/
public IClient getIClient(ClientHandle applicationHandle, UserHandle userId,
String sessionUrn) {
- // locate session from Urn
- // check Uniqueness of user + ClientHandle in the session. Update clientHandle urn accordingly.
- // wait for lock, attach to session
- // create client instance
+ // TODO Auto-generated method stub
return null;
}
- /* (non-Javadoc)
+ /**
* @see org.vamsas.client.IClientFactory#getIClient(org.vamsas.client.ClientHandle, org.vamsas.client.UserHandle)
*/
- public IClient getIClient(ClientHandle applicationHandle, UserHandle userId) throws NoDefaultSessionException {
- // create new session
- // register SimpleClient and UserHandles in session
- // create client instance
- return null;
+ public IClient getIClient(ClientHandle applicationHandle, UserHandle userId)
+ throws NoDefaultSessionException {
+ SimpleClient client = null;
+ if (this.sessionArena==null)
+ throw new Error("Improperly initialised SimpleClientFactory object - null sessionArena.");
+
+ ClientHandle clientHandle =applicationHandle;
+ //create default clientHandle with "SimpleVamsasClientApp","0.1",
+ if (clientHandle == null)
+ clientHandle = new ClientHandle("SimpleVamsasClientApp","0.1");
+
+ //check if any available session(s)
+ String[] availableSessions = this.getCurrentSessions();
+ if (availableSessions != null)
+ {//there are available sessions
+ if (availableSessions.length>1)
+ {//more than one session if available... can not choose
+
+ //represents list of session as String
+ StringBuffer sessionURNs = new StringBuffer("");
+ for (int i = 0; i< availableSessions.length ; i++)
+ {
+ sessionURNs.append(availableSessions[i]+" ");
+ }
+ throw new NoDefaultSessionException("Several sessions available, please pick one: "+sessionURNs);
+ }
+
+ //check if only one session available. if yes, open it
+ if (availableSessions.length == 1)
+ {
+ //only one session available, open it.
+ return this.getIClient(clientHandle, availableSessions[0]);
+ }
+ }
+ //no session available - create a new one
+
+
+ try
+ {
+ //create sessionDirectory
+ File sessdir = File.createTempFile("sess", ".simpleclient", this.sessionArena);
+ log.debug("Creating new session directory");
+ if (!(sessdir.delete() && sessdir.mkdir()))
+ throw new IOException("Could not make session directory "+sessdir);
+ //create session
+ VamsasSession vamsasSession = new VamsasSession(sessdir);
+
+ this.getSessionFile().addSession(new SessionHandle(new SessionUrn(vamsasSession).getSessionUrn()), false);
+ if (userId == null)
+ {
+ //create a default userHandle
+ //with current OS user and hostname
+ userId = new UserHandle(System.getProperty("user.name", System.getProperty("USERNAME","Joe Doe")),
+ System.getProperty("host.name",System.getProperty("HOSTNAME", "Unknown") ));// clientName, clientVersion, sessionPath);
+ }
+
+
+ //create simple client
+ client = new SimpleClient(userId, clientHandle, vamsasSession);
+ }
+ catch (IOException e)
+ {
+ log.error("error while creating new IClient",e);
+ }
+ catch (InvalidSessionUrnException e)
+ {
+ log.error("Unable to create new IClient. The session urn is incorrect ",e);
+ }
+
+ return client;
}
+
+
/**
- * make a new vamsas session from the data in the archive vamsasdocument
- * @param applicationHandle
- * @param userId
- * @param vamsasdocument
- * @return
+ * @return the sessionFile
*/
- public IClient openSession(ClientHandle applicationHandle, UserHandle userId, ArchiveUrn vamsasdocument) throws IOException {
- // verify applicationHandle and userId
- // TODO: verify applicationHandle and userId
- // verify vamsasdocument is a valid document.
- File vamdoc = vamsasdocument.asFile();
- log.debug("Starting new session with data from "+vamsasdocument.getSessionUrn()+"(File is : "+vamdoc+")");
- VamsasArchiveReader archive = new VamsasArchiveReader(vamdoc);
- // TODO: a real validity test. The below just checks it can be read.
- if (!archive.isValid())
- throw new IOException(vamsasdocument.getSessionUrn()+" is not a valid vamsasDocument archive.");
- // create new session directory
- if (sessionArena==null)
- throw new Error("Improperly initialised SimpleClientFactory object - null sessionArena.");
- File sessdir = File.createTempFile("sess", ".simpleclient", sessionArena);
- if (!(sessdir.delete() && sessdir.mkdir()))
- throw new IOException("Could not make session directory "+sessdir);
- VamsasSession sess = new VamsasSession(sessdir);
- // copy document into session directory
- sess.setVamsasDocument(vamsasdocument.asFile());
- // create client instance and return.
- SimpleClient client=null;
- try {
- client = new SimpleClient(userId, applicationHandle, sess);
- } catch (Exception e) {
- log.error("Couldn't make a new SimpleClient instance.",e);
- throw new IOException(e.getMessage());
+ private SessionsFile getSessionFile() throws IOException
+ {
+ if (this.sessionFile == null)
+ {
+ this.sessionFile = new SessionsFile( new File (this.sessionArena, SESSION_LIST));
+ }
+ return this.sessionFile;
}
- return client;
- }
+
- public static void main(String[] args) {
- }
+
}