added OriginalArchiveReader access method and helper method for updating archives.
authorjprocter <jprocter@compbio.dundee.ac.uk>
Wed, 30 Nov 2005 18:06:50 +0000 (18:06 +0000)
committerjprocter <jprocter@compbio.dundee.ac.uk>
Wed, 30 Nov 2005 18:06:50 +0000 (18:06 +0000)
git-svn-id: https://svn.lifesci.dundee.ac.uk/svn/repository/trunk@103 be28352e-c001-0410-b1a7-c7978e42abec

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

index 7b0532d..80f6735 100644 (file)
@@ -1,10 +1,12 @@
 package org.vamsas.client.simpleclient;
 
+import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.DataOutputStream;
 import java.io.File;
 import java.io.IOException;
-import java.io.OutputStream;
+import java.io.InputStream;
+import java.io.InputStreamReader;
 import java.io.PrintWriter;
 import java.util.Hashtable;
 import java.util.jar.JarEntry;
@@ -12,6 +14,9 @@ import java.util.jar.JarOutputStream;
 
 import org.apache.commons.logging.Log;
 import org.apache.commons.logging.LogFactory;
+import org.vamsas.client.object;
+import org.vamsas.objects.core.VAMSAS;
+import org.vamsas.objects.core.VamsasDocument;
 
 /**
  * Class for creating a vamsas archive
@@ -78,7 +83,7 @@ public class VamsasArchive {
       virginArchive=false;
     } else {
       this.original = null;
-      this.archive = archive;
+      this.archive = archive; // archive is written in place.
       virginArchive = true;
     }
   }
@@ -91,9 +96,8 @@ public class VamsasArchive {
     if (!virginArchive) {
       if (originalBackup==null && original!=null && original.exists()) {
         try {
-          accessBackup();
+          accessOriginal();
           originalBackup = odoclock.backupSessionFile(null, original.getName(), ".bak", original.getParentFile());
-          // rchive.fileLock.rafile.getChannel().truncate(0);
         }
         catch (IOException e) {
           log.warn("Problem whilst making a backup of original archive.",e);
@@ -108,6 +112,10 @@ public class VamsasArchive {
   private void updateOriginal() {
     if (original!=null) {
       if (!virginArchive) {
+        if (odoc!=null) {
+          odoc.close();
+          odoc=null;
+        }
         if (!archive.getAbsolutePath().equals(original)) {
           if (originalBackup==null) 
             makeBackup();
@@ -117,10 +125,11 @@ public class VamsasArchive {
           catch (IOException e) {
             log.error("Problem updating archive from temporary file!",e);
           }
+        } else {
+          log.warn("archive and original are the same file! ("+archive.getAbsolutePath()+")");
         }
-      } else {
-        archive.renameTo(original);
-      }
+      } // else virginArchive are put in correct place from the beginning
+      
     }
   }
   /**
@@ -129,7 +138,7 @@ public class VamsasArchive {
    */
   public File backupFile() {
     
-    if (virginArchive) {
+    if (!virginArchive) {
       makeBackup();
       return ((original==null) ? originalBackup : null);
     
@@ -142,6 +151,7 @@ public class VamsasArchive {
       return VamsasArchiveReader.VAMSASDOC;
     return VamsasArchiveReader.VAMSASXML;
   }
+  
   /**
    * @return true if Vamsas Document has been written to archive
    */
@@ -181,8 +191,12 @@ public class VamsasArchive {
     return true;
   }
   
-  File tempoutput = null;
-  SessionFile trchive = null;
+  /**
+   * opens the new archive ready for writing. If the new archive is replacing an existing one, 
+   * then the existing archive will be locked, and the new archive written to a temporary file. 
+   * The new archive will be put in place once close() is called.
+   * @throws IOException
+   */
   private void openArchive() throws IOException {
     
     if (newarchive!=null) {
@@ -196,10 +210,9 @@ public class VamsasArchive {
         throw new IOException("Badly initialised VamsasArchive object - no archive file specified.");
       }
       // lock the original
-      accessBackup();
-      // make a temporary file to write to 
-      archive = File.createTempFile(original.getName(), "new");
-      
+      accessOriginal();
+      // make a temporary file to write to
+      archive = File.createTempFile(original.getName(), "new",original.getParentFile());
     }
     
     rchive = new SessionFile(archive);
@@ -207,7 +220,6 @@ public class VamsasArchive {
     newarchive = new JarOutputStream(new BufferedOutputStream(new java.io.FileOutputStream(archive)));  
     entries = new Hashtable();
   }
-  
   /**
    * Safely initializes the VAMSAS XML document Jar Entry. 
    * @return Writer to pass to the marshalling function.
@@ -230,16 +242,15 @@ public class VamsasArchive {
   }
   /**
    * Opens and returns the applicationData output stream for the appdataReference string.
-   * TODO: Make a wrapper class to catch calls to OutputStream.close() which normally close the Jar output stream.
    * @param appdataReference
    * @return Output stream to write to
    * @throws IOException
    */
-  public OutputStream getAppDataStream(String appdataReference) throws IOException {
+  public AppDataOutputStream getAppDataStream(String appdataReference) throws IOException {
     if (newarchive!=null)
       openArchive();
     if (addValidEntry(appdataReference)) {
-      return new DataOutputStream(newarchive);
+      return new AppDataOutputStream(newarchive);
     }
     return null;
   }
@@ -313,7 +324,7 @@ public class VamsasArchive {
    * open backup for exclusive (locked) reading.
    * @throws IOException
    */
-  private void accessBackup() throws IOException {
+  private void accessOriginal() throws IOException {
     if (original!=null && original.exists()) {
       if (odoclock==null) 
         odoclock = new SessionFile(original);
@@ -333,19 +344,30 @@ public class VamsasArchive {
    * @throws IOException
    */
   public boolean transferAppDataEntry(String AppDataReference) throws IOException {
+    return transferAppDataEntry(AppDataReference, AppDataReference);
+  }
+  /**
+   * Transfers an AppDataReference from old to new vamsas archive, with a name change.
+   * @see transferAppDataEntry(String AppDataReference)
+   * @param AppDataReference
+   * @param NewAppDataReference - AppDataReference in new Archive
+   * @return
+   * @throws IOException
+   */
+  public boolean transferAppDataEntry(String AppDataReference, String NewAppDataReference) throws IOException {
     // TODO: Specify valid AppDataReference form in all VamsasArchive handlers
     if (AppDataReference==null)
-      throw new IOException("Invalid AppData Reference!");
+      throw new IOException("null AppDataReference!");
     if (original==null || !original.exists()) {
       log.warn("No backup archive exists.");
       return false;
     }
-    if (entries.containsKey(AppDataReference)) {
-      log.warn("Attempt to write '"+AppDataReference+"' twice! - IGNORED");
+    if (entries.containsKey(NewAppDataReference)) {
+      log.warn("Attempt to write '"+NewAppDataReference+"' twice! - IGNORED");
       return true;
     }
     
-    accessBackup();
+    accessOriginal();
     
     java.io.InputStream adstream = odoc.getAppdataStream(AppDataReference);
     
@@ -354,7 +376,7 @@ public class VamsasArchive {
       return false;
     }
     
-    java.io.OutputStream adout = getAppDataStream(AppDataReference);
+    java.io.OutputStream adout = getAppDataStream(NewAppDataReference);
     // copy over the bytes
     int written=-1;
     long count=0;
@@ -366,10 +388,10 @@ public class VamsasArchive {
         count+=written;
       }
     } while (written>-1);
-    log.debug("Sucessfully transferred AppData for "+AppDataReference+" ("+count+" bytes)");
+    log.debug("Sucessfully transferred AppData for '"
+        +AppDataReference+"' as '"+NewAppDataReference+"' ("+count+" bytes)");
     return true;
   }
-  
   /**
    * Tidies up and closes archive, removing any backups that were created.
    * NOTE: It is up to the caller to delete the original archive backup obtained from backupFile()
@@ -386,4 +408,49 @@ public class VamsasArchive {
       log.warn("Attempt to close archive that has not been opened for writing.");
     }
   }
+  /**
+   * Access original archive if it exists, pass the reader to the client
+   * Note: this is NOT thread safe and a call to closeArchive() will by necessity 
+   * close and invalidate the VamsasArchiveReader object.
+   * @return null if no original archive exists.
+   */
+  public VamsasArchiveReader getOriginalArchiveReader() throws IOException {
+    if (!virginArchive) {
+      accessOriginal();
+      return odoc;
+    }
+    return null;
+  }
+  
+  /**
+   * Access original document if it exists, and get VAMSAS root objects.
+   * @return vector of vamsas roots from original document
+   * @throws IOException
+   */
+  public static object[] getOriginalRoots(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.getVAMSAS();
+        
+      } else {
+        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)
+            return root;
+        }
+      }
+    }
+    return null;
+  }
+
 }