implement new client factory methods to open a stored session document in a new vamsa...
[vamsas.git] / src / uk / ac / vamsas / client / simpleclient / SimpleClientFactory.java
index b4a74d3..27aaf77 100644 (file)
@@ -1,12 +1,12 @@
-/*
-* VAMSAS Project
-*
-
-* 
-* Dec 13, 2006 
-*
-*/
+/**
+ * 
+ * VAMSAS Project
+ *
+ * 
+ * Dec 13, 2006 
+ *
+ */
+
 package uk.ac.vamsas.client.simpleclient;
 
 import java.io.File;
@@ -14,13 +14,13 @@ import java.io.File;
 import java.io.IOException;
 import java.net.MalformedURLException;
 
-
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
 
 import uk.ac.vamsas.client.ClientHandle;
 import uk.ac.vamsas.client.IClient;
 import uk.ac.vamsas.client.IClientFactory;
+import uk.ac.vamsas.client.InvalidSessionDocumentException;
 import uk.ac.vamsas.client.InvalidSessionUrnException;
 import uk.ac.vamsas.client.NoDefaultSessionException;
 import uk.ac.vamsas.client.SessionHandle;
@@ -28,93 +28,87 @@ import uk.ac.vamsas.client.UserHandle;
 
 /**
  * 
- * creates a session arena in the user home directory under .vamsas.
- * Each session has its own subdirectory.
+ * creates a session arena in the user home directory under .vamsas. Each
+ * session has its own subdirectory.
  */
 public class SimpleClientFactory implements IClientFactory {
 
   private static Log log = LogFactory.getLog(SimpleClientFactory.class);
 
   private File sessionArena = null;
-  
+
   private String vamsasSubdirectoryName = ".vamsas";
-  
- private SimpleSessionManager sessionManager = null;
-  private static final String SESSION_LIST="sessions.obj";
-  
-  //private   String[] currentlyAvailableDessions = null; 
-  
+
+  private SimpleSessionManager sessionManager = 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. 
-   *
+   * 
+   * Inits the sessionarena to the directory .vamsas of the user home directory.
+   * 
    */
-  public SimpleClientFactory() throws IOException
-  {
-   // sessionArena
-    
-    //retrieves user home directory
+  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));
-    
+    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();
+    // this.initFactoryObjects();
   }
-  
-  
+
   /**
-   * Create a client factory that works with sessions at the given
-   * path.
-   * @param path path to directory called  session arena, where will be created session directories and session files.
+   * Create a client factory that works with sessions at the given 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.
+   * 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
+   * @param path
+   *          path to a directory to use
+   * @throws IOException
+   *           if the path is incorrect
    */
-  private void  initSessionArena (String path) throws IOException
-  {
+  private void initSessionArena(String path) throws IOException {
     // Check path is valid and read/writeable.
-    File arenaFile = new File (path);
-    if (!arenaFile.exists())
-    {
-      if (! arenaFile.mkdirs())
-      {
+    File arenaFile = new File(path);
+    if (!arenaFile.exists()) {
+      if (!arenaFile.mkdirs()) {
         this.sessionArena = null;
-        throw(new IOException("Unable to create a directory called "+path));
+        throw (new IOException("Unable to create a directory called " + path));
       }
     }
-    if (arenaFile.exists() && arenaFile.isDirectory() && arenaFile.canRead() && arenaFile.canWrite()) 
-      {
-        this.sessionArena = arenaFile;
-      } 
-    else
-      {
+    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));
-      }
+      throw (new IOException("Cannot read and write to a directory called "
+          + path));
+    }
   }
-  
-  
-
-  
 
   /**
    * @see uk.ac.vamsas.client.IClientFactory#getIClient(uk.ac.vamsas.client.ClientHandle)
    * 
-   * Creates a IClient object, using default UserHandle with system variables:"user.name" or "USERNAME")),
-            "host.name" or "HOSTNAME" 
+   * 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 {
@@ -126,125 +120,154 @@ public class SimpleClientFactory implements IClientFactory {
 
   /**
    * the URN should be something like simpleclient:FILEPATH URL encoded
-   * @see uk.ac.vamsas.client.IClientFactory#getIClient(uk.ac.vamsas.client.ClientHandle, java.lang.String)
+   * 
+   * @see uk.ac.vamsas.client.IClientFactory#getIClient(uk.ac.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.
+    // 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
-    log.debug("Trying to create session with URN "+sessionUrn);
+    log.debug("Trying to create session with URN " + sessionUrn);
     return this.getIClient(applicationHandle, null, sessionUrn);
-  
+
   }
 
-  private File convertSessionUrnToFile(String sessionUrn) throws InvalidSessionUrnException
-  {
-    if (sessionUrn == null)
-      {
-        log.debug("Incorrect URN: can not open session.");
-        throw new InvalidSessionUrnException();
-      }
-    
+  private File convertSessionUrnToFile(String sessionUrn)
+      throws InvalidSessionUrnException {
+    if (sessionUrn == null) {
+      log.debug("Incorrect URN: can not open session.");
+      throw new InvalidSessionUrnException();
+    }
+
     SessionUrn urn = new SessionUrn(sessionUrn);
-   return urn.asFile();
-    
+    return urn.asFile();
+
   }
-  
+
   /**
-   * @see uk.ac.vamsas.client.IClientFactory#getIClient(uk.ac.vamsas.client.ClientHandle, uk.ac.vamsas.client.UserHandle, java.lang.String)
+   * @see uk.ac.vamsas.client.IClientFactory#getIClient(uk.ac.vamsas.client.ClientHandle,
+   *      uk.ac.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.
+    // 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
     IClient client = null;
-    
+
+    // TODO: implement 'opening stored session' opening mechanism
+    // 1. existing session document URL is vdoc://... ?
+    // 2. check for sessionUrn being of this form.
+    // 3. if it is - locate the file and pass to new VamsasSession
+
     try {
       File sessionDirectory = this.convertSessionUrnToFile(sessionUrn);
-      //create session
-      log.debug("found session directory "+sessionDirectory.getAbsolutePath());
+      // create session
+      log
+          .debug("found session directory "
+              + sessionDirectory.getAbsolutePath());
       VamsasSession vamsasSession = new VamsasSession(sessionDirectory);
-   /*   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,  applicationHandle,  vamsasSession);*/
-      client = this.initClient(sessionDirectory, userId, applicationHandle);
+      
+      /*
+       * 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,
+       * applicationHandle, vamsasSession);
+       */
+      client = this.initClient(sessionDirectory, userId, applicationHandle, null);
     } catch (MalformedURLException e) {
-      log.error("error while creating new IClient: incorrect session urn",e);
+      log.error("error while creating new IClient: incorrect session urn", e);
+      client = null;
+    } catch (InvalidSessionDocumentException e)
+    {
+      log.error("error while creating new IClient: invalid session document", e);
       client = null;
-     
     } catch (InvalidSessionUrnException e) {
-      log.error("error while creating new IClient: incorrect session urn",e);
+      log.error("error while creating new IClient: incorrect session urn", e);
       client = null;
     } catch (IOException e) {
-      log.error("error while creating new IClient: file access error",e);
+      log.error("error while creating new IClient: file access error", e);
       client = null;
     }
     return client;
   }
-
-  
-  private IClient initClient( File sessdir, UserHandle userId, ClientHandle clientHandle) throws IOException, InvalidSessionUrnException
-  {
+  /**
+   * initialise the vamsas session state and create a SimpleClient object to connect to it
+   * @param sessdir newly created or existing session directory
+   * @param userId 
+   * @param clientHandle
+   * @param vamsasDocument null or a document to pass to SimpleCLient to write into the sessdir
+   * @return the client
+   * @throws IOException if there are problems in session or client creation or if the session already has a vamsasDocument
+   * @throws InvalidSessionUrnException for a malformed sessdir
+   */
+  private IClient initClient(File sessdir, UserHandle userId,
+      ClientHandle clientHandle, File vamsasDocument) throws IOException, InvalidSessionUrnException, InvalidSessionDocumentException {
     IClient client = null;
-//  create session
-    VamsasSession vamsasSession = new VamsasSession(sessdir);
-  
-    this.getSessionManager().addSession(new SessionHandle(new SessionUrn(vamsasSession).getSessionUrn()));
-    if (userId == null)
-      {
-  //create a default userHandle
-     //   userId = new UserHandle(System.getProperty("user.name", System.getProperty("USERNAME","Joe Doe")),
-       //   System.getProperty("host.name",System.getProperty("HOSTNAME", "Unknown") ));// clientName, clientVersion,  sessionPath);
-        userId = new UserHandle(null, null);
-        
-      }
-    
-    //FullName and organisation should not be null (otherwise UserHandle equals method raises an java.lang.NullPointerException )
-    //use    current OS user and hostname, if null
-    if ( userId.getFullName() == null)
-      {
-        userId.setFullName(System.getProperty("user.name", System.getProperty("USERNAME","Joe Doe")));
+    // create session
+    VamsasSession vamsasSession = null;
+    if (vamsasDocument==null)
+    {
+      vamsasSession = new VamsasSession(sessdir);
+    } else {
+      vamsasSession = new VamsasSession(sessdir, vamsasDocument);
+    }
+
+    this.getSessionManager().addSession(
+        new SessionHandle(new SessionUrn(vamsasSession).getSessionUrn()));
+    if (userId == null) {
+      // create a default userHandle
+      // userId = new UserHandle(System.getProperty("user.name",
+      // System.getProperty("USERNAME","Joe Doe")),
+      // System.getProperty("host.name",System.getProperty("HOSTNAME",
+      // "Unknown") ));// clientName, clientVersion, sessionPath);
+      userId = new UserHandle(null, null);
+    }
+
+    // FullName and organisation should not be null (otherwise UserHandle equals
+    // method raises an java.lang.NullPointerException )
+    // use current OS user and hostname, if null
+    if (userId.getFullName() == null) {
+      userId.setFullName(System.getProperty("user.name", System.getProperty(
+          "USERNAME", "Joe Doe")));
+    }
+
+    if (userId.getOrganization() == null) {
+      userId.setOrganization(System.getProperty("host.name", System
+          .getProperty("HOSTNAME", "Unknown")));
+    }
+
+    if (clientHandle == null)
+      clientHandle = new ClientHandle("SimpleVamsasClientApp", "0.1");
+    else {
+      if (clientHandle.getClientName() == null) {
+        clientHandle.setClientName("SimpleVamsasClientApp");
       }
-        
-    if (userId.getOrganization() == null)
-      {
-        userId.setOrganization( System.getProperty("host.name",System.getProperty("HOSTNAME", "Unknown") ));
+      if (clientHandle.getVersion() == null) {
+        clientHandle.setVersion("0.1");
       }
-      
-    if (clientHandle == null)
-      clientHandle = new ClientHandle("SimpleVamsasClientApp","0.1");
-     else
-       {
-         if (clientHandle.getClientName() == null)
-           {
-             clientHandle.setClientName("SimpleVamsasClientApp");
-           }
-         if (clientHandle.getVersion() == null)
-           {
-             clientHandle.setVersion("0.1");
-           }
-       }
-    
-  //create simple client
-     client = new SimpleClient(userId,  clientHandle,  vamsasSession);
-     vamsasSession.addClient(client);
-     vamsasSession.setSessionManager(this.getSessionManager());
-     return client;
+    }
+
+    // create simple client
+    client = new SimpleClient(userId, clientHandle, vamsasSession);
+    vamsasSession.addClient((SimpleClient) client);
+    vamsasSession.setSessionManager(this.getSessionManager());
+    return client;
   }
+
   /**
-   * @see uk.ac.vamsas.client.IClientFactory#getIClient(uk.ac.vamsas.client.ClientHandle, uk.ac.vamsas.client.UserHandle)
+   * @see uk.ac.vamsas.client.IClientFactory#getIClient(uk.ac.vamsas.client.ClientHandle,
+   *      uk.ac.vamsas.client.UserHandle)
    */
   public IClient getIClient(ClientHandle applicationHandle, UserHandle userId)
       throws NoDefaultSessionException {
@@ -252,116 +275,176 @@ public class SimpleClientFactory implements IClientFactory {
     // register SimpleClient and UserHandles in session
     // create client instance
     IClient 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 (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");
-    else
-      {
-        if (clientHandle.getClientName() == null)
-        {
-          clientHandle.setClientName("SimpleVamsasClientApp");
-        }
-      
-    
-    if (clientHandle.getVersion() == null)
-      {
-        clientHandle.setVersion("0.1");
+      clientHandle = new ClientHandle("SimpleVamsasClientApp", "0.1");
+    else {
+      if (clientHandle.getClientName() == null) {
+        clientHandle.setClientName("SimpleVamsasClientApp");
       }
+
+      if (clientHandle.getVersion() == null) {
+        clientHandle.setVersion("0.1");
       }
-    //check if any available session(s)
+    }
+    // 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]);
-          }
+    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);
       }
-    //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);*/
-       client = this.initClient(sessdir, userId, clientHandle);
-      } 
-    catch (IOException e) 
-      {
-        log.error("error while creating new IClient",e);
+
+      // 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]);
+      } else {
+        log.debug("No active session found");
       }
-    catch (InvalidSessionUrnException e) 
+    }
+    // no session available - create a new one
+    try {
+      client = clientInNewSession(userId, clientHandle, null);
+    } catch (Exception e)
+    {
+      throw new Error("IMPLEMENTATION ERROR: unexpected exception when creating a new session to connect to.",e);
+    }
+    return client;
+  }
+
+  /**
+   * create a new session directory and possibly import an existing document into it
+   * @param userId
+   * @param clientHandle
+   * @param vamsasDocument null or a document file to copy into the new session
+   * @return null or a valid IClient instance
+   */
+  private IClient clientInNewSession(UserHandle userId,
+      ClientHandle clientHandle, File vamsasDocument) throws InvalidSessionDocumentException, InvalidSessionUrnException{
+
+    IClient client = null;
+    try {
+      // try and make a friendly session name
+      String sesspref = "";
+      if (vamsasDocument!=null)
       {
-        log.error("Unable to create new IClient. The session urn is incorrect ",e);
+        sesspref = vamsasDocument.getName().replaceAll("([^-A-Za-z0-9]|\\.vdj)", "");
       }
-   
-      return client;
-  }
+      sesspref += (new java.util.Date()).toString().replaceAll("[^-A-Za-z0-9]","_");
+      // create sessionDirectory
+      File sessdir = new File(sessionArena, sesspref+".simpleclient");
+      if (sessdir.exists())
+      {  
+        // make a unique session name
+        sessdir = File.createTempFile(sesspref, ".simpleclient",
+          sessionArena);
+      } else {
+        if (!sessdir.createNewFile())
+        {
+          throw new Error("VAMSAS Implementation error : sesspref friendly session name is invalid on this platform - please tell the authors!");
+        }
+      }
+      log.debug("Creating new session  directory");
+      if (!(sessdir.delete() && sessdir.mkdir()))
+        throw new IOException("Could not make session directory " + sessdir);
+      client = initClient(sessdir, userId, clientHandle, vamsasDocument);
+    } catch (IOException e) {
+      log.error("error while creating new IClient", e);
+    } catch (InvalidSessionUrnException e) {
+      log.error("Unable to create new IClient. The new session urn is malformed.",
+          e);
+    }
 
+    return client;
+  }
 
   /**
    * @see uk.ac.vamsas.client.IClientFactory#getCurrentSessions()
    */
   public String[] getCurrentSessions() {
-    String [] sessions = null;
+    String[] sessions = null;
     try {
-      sessions =this.getSessionManager().getCurrentSessions();
+      sessions = this.getSessionManager().getCurrentSessions();
     } catch (IOException e) {
-     log.error("Unable to get available sessions",e);
-     sessions = null;
+      log.error("Unable to get available sessions", e);
+      sessions = null;
     }
     return sessions;
   }
 
-
   /**
    * @return the sessionFile
    */
-  private SimpleSessionManager getSessionManager()  throws IOException
+  private SimpleSessionManager getSessionManager() throws IOException {
+    if (this.sessionManager == null) {
+      this.sessionManager = new SimpleSessionManager(new File(
+          this.sessionArena, SESSION_LIST));
+    }
+    return this.sessionManager;
+  }
+
+  public IClient getNewSessionIClient(ClientHandle applicationHandle) {
+    try {
+      return clientInNewSession(null, applicationHandle, null);
+    }
+    catch (Exception e) {
+      log.error("Failed to create new session for app with default user.",e);
+    }
+    return null;
+  }
+
+  public IClient getNewSessionIClient(ClientHandle applicationHandle,
+      UserHandle userId) {
+    try {
+      return clientInNewSession(userId, applicationHandle, null);
+    } catch (Exception e) {
+      log.error("Failed to create new session for app and user.",e);
+    }
+    return null;
+  }
+  private void checkImportedDocument(File vamsasDocument) throws InvalidSessionDocumentException 
+  {
+    if (!vamsasDocument.exists())
     {
-      if (this.sessionManager == null)
-        {
-          this.sessionManager = new SimpleSessionManager( new File (this.sessionArena, SESSION_LIST));
-        }
-      return this.sessionManager;
+      throw new InvalidSessionDocumentException("File "+vamsasDocument+" does not exist");
+    }
+    if (!vamsasDocument.canRead())
+    {
+      throw new InvalidSessionDocumentException("File "+vamsasDocument+" does not exist");
     }
+  }
+  public IClient openAsNewSessionIClient(ClientHandle applicationHandle,
+      File vamsasDocument) throws InvalidSessionDocumentException {
+    checkImportedDocument(vamsasDocument);  
+    try {
+      return clientInNewSession(null, applicationHandle, vamsasDocument);
+    } catch (InvalidSessionUrnException e)
+    {
+      throw new InvalidSessionDocumentException("Unexpected exception", e);
+    }
+  }
 
-  
+  public IClient openAsNewSessionIClient(ClientHandle applicationHandle,
+      UserHandle userId, File vamsasDocument) throws InvalidSessionDocumentException {
+    checkImportedDocument(vamsasDocument);  
+    try {
+    return clientInNewSession(userId, applicationHandle, vamsasDocument);
+    } catch (InvalidSessionUrnException e)
+    {
+    throw new InvalidSessionDocumentException("Unexpected exception", e);
+    }
+  }
 
 }