debugging.
authorjprocter <jprocter@compbio.dundee.ac.uk>
Sun, 15 Jan 2006 17:58:15 +0000 (17:58 +0000)
committerjprocter <jprocter@compbio.dundee.ac.uk>
Sun, 15 Jan 2006 17:58:15 +0000 (17:58 +0000)
git-svn-id: https://svn.lifesci.dundee.ac.uk/svn/repository/trunk@132 be28352e-c001-0410-b1a7-c7978e42abec

src/org/vamsas/client/simpleclient/SessionFile.java
src/org/vamsas/client/simpleclient/VamsasArchive.java

index b73a47f..30abd99 100644 (file)
@@ -112,7 +112,7 @@ public class SessionFile {
     log.debug("Updating "+sessionFile.getAbsolutePath()+" from "+newData.sessionFile.getAbsolutePath());
     if (newData==null)
       throw new IOException("Null newData object.");
-    if (newData.sessionFile!=null)
+    if (newData.sessionFile==null)
       throw new IOException("Null SessionFile in newData.");
       
     lockFile(extantLock);  
index dcd0f54..fab9ef2 100644 (file)
@@ -18,10 +18,13 @@ import org.vamsas.client.object;
 import org.vamsas.objects.core.ApplicationData;
 import org.vamsas.objects.core.VAMSAS;
 import org.vamsas.objects.core.VamsasDocument;
+import org.vamsas.objects.utils.DocumentStuff;
+import org.vamsas.objects.utils.ProvenanceStuff;
+import org.vamsas.objects.utils.document.VersionEntries;
 
 /**
- * Class for creating a vamsas archive
- * (with backups)
+ * Class for high-level io and Jar manipulation involved in creating 
+ * or updating a vamsas archive (with backups).
  * Writes to a temporary file and then swaps new file for backup.
  * uses the sessionFile locking mechanism for safe I/O
  * @author jimp
@@ -30,7 +33,7 @@ import org.vamsas.objects.core.VamsasDocument;
 public class VamsasArchive {
   private static Log log = LogFactory.getLog(VamsasArchive.class);
   /**
-   * destination of new archive data
+   * destination of new archive data (tempfile if virginarchive=true, original archive location otherwise)
    */
   java.io.File archive=null;
   /**
@@ -38,7 +41,7 @@ public class VamsasArchive {
    */
   SessionFile rchive=null; 
   /**
-   * original archive file that is to be updated
+   * original archive file to be updated (or null if virgin) where new data will finally reside
    */
   java.io.File original=null;
   /**
@@ -67,13 +70,15 @@ public class VamsasArchive {
   private boolean virginArchive=false;
   /**
    * Create a new vamsas archive
-   * nb. No file locks are made until open() is called.
+   * File locks are made immediately to avoid contention
+   *  
    * @param archive - file spec for new vamsas archive
    * @param vamsasdocument true if archive is to be a fully fledged vamsas document archive
+   * @throws IOException if call to accessOriginal failed for updates, or openArchive failed.
    */
-  public VamsasArchive(File archive, boolean vamsasdocument) {
+  public VamsasArchive(File archive, boolean vamsasdocument) throws IOException {
     super();
-    if (archive==null || (archive!=null && archive.canWrite())) {
+    if (archive==null || (archive!=null && !archive.canWrite())) {
       log.fatal("Invalid parameters for VamsasArchive constructor:"+((archive!=null) 
           ? "File cannot be overwritten." : "Null Object not valid constructor parameter"));
     }
@@ -82,14 +87,21 @@ public class VamsasArchive {
       this.original = archive;
       this.archive = null;       // archive will be a temp file when the open method is called
       virginArchive=false;
+      try {
+        this.accessOriginal();
+      } catch (IOException e)  {
+        throw new IOException("Lock failed for existing archive"+archive);
+      }
     } else {
       this.original = null;
       this.archive = archive; // archive is written in place.
       virginArchive = true;
     }
+    this.openArchive();
   }
   /**
    * name of backup of existing archive that has been updated/overwritten.
+   * onlu one backup will be made - and this is it.
    */
   File originalBackup = null;
   
@@ -106,31 +118,32 @@ public class VamsasArchive {
       }
     }
   }
+
   /**
    * called after archive is written to put file in its final place
-   * TODO: FINISH original should have sessionFile, and archive should also have sessionFile
+   * TODO: FINISH ?? original should have sessionFile, and archive should also have sessionFile
    */
   private void updateOriginal() {
-    if (original!=null) {
-      if (!virginArchive) {
+    if (!virginArchive) {
+      // make sure original document really is backed up and then overwrite it.
         if (odoc!=null) {
+          // try to shut the odoc reader.
           odoc.close();
-          odoc=null;
+          odoc = null;
         }
-        if (!archive.getAbsolutePath().equals(original)) {
-          if (originalBackup==null) 
-            makeBackup();
-          try {
-            odoclock.updateFrom(null, rchive);
-          }
-          catch (IOException e) {
-            log.error("Problem updating archive from temporary file!",e);
-          }
-        } else {
-          log.warn("archive and original are the same file! ("+archive.getAbsolutePath()+")");
+        // Make a backup if it isn't done already
+        if (originalBackup==null)
+          makeBackup();
+        try {
+          // copy new Archive data that was writen to a temporary file
+          odoclock.updateFrom(null, rchive);
         }
-      } // else virginArchive are put in correct place from the beginning
-      
+        catch (IOException e) {
+          log.error("Problem updating archive from temporary file! - backup in '"
+              +backupFile().getAbsolutePath()+"'",e);
+        }
+    } else {
+      // don't need to do anything.
     }
   }
   /**
@@ -141,12 +154,15 @@ public class VamsasArchive {
     
     if (!virginArchive) {
       makeBackup();
-      return ((original==null) ? originalBackup : null);
-    
+      return ((original!=null) ? originalBackup : null);
+      
     }
     return null;
   }
-  
+  /**
+   * 
+   * @return JarEntry name for the vamsas XML stream in this archive
+   */
   protected String getDocumentJarEntry() {
     if (vamsasdocument)
       return VamsasArchiveReader.VAMSASDOC;
@@ -161,7 +177,7 @@ public class VamsasArchive {
       log.warn("isDocumentWritten called for unopened archive.");
     if (entries!=null) {
       if (entries.containsKey(getDocumentJarEntry()))
-          return true;
+        return true;
     }
     return false;
   }
@@ -204,16 +220,18 @@ public class VamsasArchive {
       log.warn("openArchive() called multiple times.");
       throw new IOException("Vamsas Archive '"+archive.getAbsolutePath()+"' is already open.");
     }
-    
-    if (archive==null) {
-      if (original==null) {
-        log.warn("openArchive called on uninitialised VamsasArchive object.");
-        throw new IOException("Badly initialised VamsasArchive object - no archive file specified.");
-      }
+    if (archive==null && (virginArchive || original==null)) {
+      log.warn("openArchive called on uninitialised VamsasArchive object.");
+      throw new IOException("Badly initialised VamsasArchive object - no archive file specified.");
+    }
+    if (!virginArchive) {
       // lock the original
       accessOriginal();
       // make a temporary file to write to
-      archive = File.createTempFile(original.getName(), "new",original.getParentFile());
+      archive = File.createTempFile(original.getName(), ".new",original.getParentFile());
+    } else {
+      if (archive.exists())
+        log.warn("New archive file name already in use! Possible lock failure imminent?");
     }
     
     rchive = new SessionFile(archive);
@@ -264,6 +282,7 @@ public class VamsasArchive {
     if (newarchive!=null) {
       try { 
         newarchive.close();
+        
       } catch (Exception e) {};
       if (!virginArchive) {
         // then there is something to recover.
@@ -275,21 +294,23 @@ public class VamsasArchive {
           }
           SessionFile bckup = new SessionFile(originalBackup);
           
-            try {
-              rchive.updateFrom(null,bckup); // recover from backup file.
-              bckup.unlockFile();
-              bckup=null;
-              originalBackup.delete();
-            }
-            catch (Exception e) {
-              log.warn("Problems when trying to cancel Archive "+archive.getAbsolutePath(), e);
-              return false;
-            }
+          try {
+            rchive.updateFrom(null, bckup); // recover from backup file.
+            bckup.unlockFile();
+            bckup=null;
+            originalBackup.delete();
+            originalBackup=null;
+          }
+          catch (Exception e) {
+            log.warn("Problems when trying to cancel Archive "+archive.getAbsolutePath(), e);
+            return false;
+          }
         }
         // original is untouched
         // just delete temp files
         
-        }
+        
+      }
     } else {
       log.info("cancelArchive called before archive("+original.getAbsolutePath()+") has been opened!");
     }
@@ -302,14 +323,17 @@ public class VamsasArchive {
    *
    */
   private void closeAndReset() {
-    rchive.unlockFile();
-    rchive = null;
+    if (rchive!=null) {
+      rchive.unlockFile();
+      rchive = null;
+    }
     if (original!=null) {
       if (odoc!=null) {
         odoc.close();
         odoc=null;
       }
-      archive.delete();
+      if (archive!=null)
+        archive.delete();
       if (odoclock!=null) {
         odoclock.unlockFile();
         odoclock = null;
@@ -319,10 +343,10 @@ public class VamsasArchive {
     original=null;
     entries=null;
   }
-
+  
   private final int _TRANSFER_BUFFER=4096*4;
   /**
-   * open backup for exclusive (locked) reading.
+   * open original archive file for exclusive (locked) reading.
    * @throws IOException
    */
   private void accessOriginal() throws IOException {
@@ -334,7 +358,7 @@ public class VamsasArchive {
         odoc = new VamsasArchiveReader(original);
     }
   }
-
+  
   /**
    * Convenience method to copy over the referred entry from the backup to the new version.
    * Warning messages are raised if no backup exists or the 
@@ -439,7 +463,7 @@ public class VamsasArchive {
    * @throws IOException
    */
   public static object[] getOriginalRoots(VamsasArchive ths) throws IOException, 
-    org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException {
+  org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException {
     VamsasArchiveReader oReader = ths.getOriginalArchiveReader();
     if (oReader!=null) {
       
@@ -448,7 +472,7 @@ public class VamsasArchive {
         VamsasDocument doc = VamsasDocument.unmarshal(vdoc);
         if (doc!=null) 
           return doc.getVAMSAS();
-        // TODO ensure embedded appDatas are garbage collected 
+        // TODO ensure embedded appDatas are garbage collected to save memory
       } else {
         InputStream vxmlis = oReader.getVamsasXmlStream();
         if (vxmlis!=null) { // Might be an old vamsas file.
@@ -463,6 +487,73 @@ public class VamsasArchive {
     }
     return null;
   }
-  
-
+  /**
+   * Access and return current vamsas Document, if it exists, or create a new one 
+   * (without affecting VamsasArchive object state - so is NOT THREAD SAFE)
+   * TODO: possibly modify internal state to lock low-level files 
+   * (like the IClientDocument interface instance constructer would do) 
+   * @see org.vamsas.simpleclient.VamsasArchive.getOriginalVamsasDocument for additional caveats
+   * 
+   * @return
+   * @throws IOException
+   * @throws org.exolab.castor.xml.MarshalException
+   * @throws org.exolab.castor.xml.ValidationException
+   */
+  public VamsasDocument getVamsasDocument() throws IOException, 
+  org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException {
+    VamsasDocument doc = getOriginalVamsasDocument(this);
+    if (doc!=null)
+      return doc;
+    // Create a new document and return it
+    doc = DocumentStuff.newVamsasDocument(new VAMSAS[] { new VAMSAS()}, 
+        ProvenanceStuff.newProvenance("org.vamsas.simpleclient.VamsasArchive", "Created new empty document")
+        , VersionEntries.latestVersion());
+    return doc;
+  }
+  /**
+   * Access the original vamsas document for a VamsasArchive class, and return it.
+   * Users of the VamsasArchive class should use the getVamsasDocument method to retrieve
+   * the current document - only use this one if you want the 'backup' version.
+   * TODO: catch OutOfMemoryError - they are likely to occur here.
+   * NOTE: vamsas.xml datastreams are constructed as 'ALPHA_VERSION' vamsas documents.
+   * @param ths
+   * @return null if no document exists.
+   * @throws IOException
+   * @throws org.exolab.castor.xml.MarshalException
+   * @throws org.exolab.castor.xml.ValidationException
+   */
+  public static VamsasDocument getOriginalVamsasDocument(VamsasArchive ths) throws IOException, 
+  org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException {
+    VamsasArchiveReader oReader = ths.getOriginalArchiveReader();
+    if (oReader!=null) {
+      if (oReader.isValid()) {
+        InputStreamReader vdoc = new InputStreamReader(oReader.getVamsasDocumentStream());
+        VamsasDocument doc = VamsasDocument.unmarshal(vdoc);
+        if (doc!=null) 
+          return doc;
+      } else {
+        // deprecated data handler
+        InputStream vxmlis = oReader.getVamsasXmlStream();
+        if (vxmlis!=null) { // Might be an old vamsas file.
+          BufferedInputStream ixml = new BufferedInputStream(oReader.getVamsasXmlStream());
+          InputStreamReader vxml = new InputStreamReader(ixml);
+          VAMSAS root[] = new VAMSAS[1];
+          root[0] = VAMSAS.unmarshal(vxml);
+          if (root[0]!=null) {
+            log.debug("Reading old format vamsas.xml into a dummy document.");
+            VamsasDocument doc = DocumentStuff.newVamsasDocument(root, 
+                ProvenanceStuff.newProvenance(
+                    "org.vamsas.simpleclient.VamsasArchive", // TODO: VAMSAS: decide on 'system' operations provenance form
+                    "Vamsas Document constructed from vamsas.xml in <file>" 
+                    // TODO: VAMSAS: decide on machine readable info embedding in provenance should be done
+                    +ths.original+"</file>"), VersionEntries.ALPHA_VERSION);
+            root[0]=null;
+            root=null;
+            return doc;
+          }
+        }
+      }
+    } // otherwise - there was no valid original document to read.
+    return null;    
+  }
 }