X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=src%2Forg%2Fvamsas%2Fclient%2Fsimpleclient%2FVamsasArchive.java;h=93c775caf209dc7e64236971585013dd10119196;hb=99cfce21cfd9e358f4f5ae628498ebad75c0b932;hp=721cdf96a7c8a5e32db019fc9c4e1184f7246e99;hpb=1f066b7b070342e9a41189e039e80d2fefb57976;p=vamsas.git diff --git a/src/org/vamsas/client/simpleclient/VamsasArchive.java b/src/org/vamsas/client/simpleclient/VamsasArchive.java index 721cdf9..93c775c 100644 --- a/src/org/vamsas/client/simpleclient/VamsasArchive.java +++ b/src/org/vamsas/client/simpleclient/VamsasArchive.java @@ -11,6 +11,8 @@ import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.util.Hashtable; +import java.util.Iterator; +import java.util.Vector; import java.util.jar.JarEntry; import java.util.jar.JarOutputStream; @@ -22,10 +24,11 @@ import org.vamsas.client.SessionHandle; import org.vamsas.client.UserHandle; import org.vamsas.client.VorbaIdFactory; import org.vamsas.client.VorbaXmlBinder; -import org.vamsas.client.object; +import org.vamsas.client.Vobject; import org.vamsas.objects.core.ApplicationData; import org.vamsas.objects.core.VAMSAS; import org.vamsas.objects.core.VamsasDocument; +import org.vamsas.objects.utils.AppDataReference; import org.vamsas.objects.utils.DocumentStuff; import org.vamsas.objects.utils.ProvenanceStuff; import org.vamsas.objects.utils.document.VersionEntries; @@ -41,13 +44,78 @@ import org.vamsas.objects.utils.document.VersionEntries; public class VamsasArchive { private static Log log = LogFactory.getLog(VamsasArchive.class); /** + * Access original document if it exists, and get VAMSAS root objects. + * @return vector of vamsas roots from original document + * @throws IOException + */ + public static Vobject[] 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(); + // TODO ensure embedded appDatas are garbage collected to save memory + } 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; + } + /** + * 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 { + return VamsasArchive.getOriginalVamsasDocument(ths, null); + } + /** + * Uses VorbaXmlBinder to retrieve the VamsasDocument from the original archive referred to by ths + * @param ths + * @param vorba + * @return + * @throws IOException + * @throws org.exolab.castor.xml.MarshalException + * @throws org.exolab.castor.xml.ValidationException + */ + public static VamsasDocument getOriginalVamsasDocument(VamsasArchive ths, VorbaIdFactory vorba) throws IOException, + org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException { + VamsasArchiveReader oReader = ths.getOriginalArchiveReader(); + if (oReader!=null) { + ths.setVorba(vorba); + return ths.vorba.getVamsasDocument(oReader); + } + // otherwise - there was no valid original document to read. + return null; + } + /** * destination of new archive data (tempfile if virginarchive=true, original archive location otherwise) */ java.io.File archive=null; /** * locked IO handler for new archive file */ - SessionFile rchive=null; + SessionFile rchive=null; /** * original archive file to be updated (or null if virgin) where new data will finally reside */ @@ -56,6 +124,7 @@ public class VamsasArchive { * original archive IO handler */ SessionFile odoclock = null; + Lock destinationLock = null; /** * Original archive reader class */ @@ -72,10 +141,35 @@ public class VamsasArchive { * JarEntries written to archive */ Hashtable entries = null; + /** * true if we aren't just updating an archive */ private boolean virginArchive=false; + + /** + * name of backup of existing archive that has been updated/overwritten. + * onlu one backup will be made - and this is it. + */ + File originalBackup = null; + + boolean donotdeletebackup=false; + private final int _TRANSFER_BUFFER=4096*4; + protected SimpleDocument vorba = 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 + */ + private VamsasDocument _doc=null; + /** * Create a new vamsas archive * File locks are made immediately to avoid contention @@ -85,14 +179,35 @@ public class VamsasArchive { * @throws IOException if call to accessOriginal failed for updates, or openArchive failed. */ public VamsasArchive(File archive, boolean vamsasdocument) throws IOException { + this(archive, false, vamsasdocument, null); + } + public VamsasArchive(File archive, boolean vamsasdocument, boolean overwrite) throws IOException { + this(archive, overwrite, vamsasdocument, null); + } + /** + * + * @param archive file to write + * @param overwrite true if original contents should be deleted + * @param vamsasdocument true if a proper VamsasDocument archive is to be written. + * @param extantLock SessionFile object holding a lock for the archive + * @throws IOException + */ + public VamsasArchive(File archive, boolean overwrite, boolean vamsasdocument, SessionFile extantLock) throws IOException { super(); - if (archive==null || (archive!=null && !archive.canWrite())) { - log.fatal("Invalid parameters for VamsasArchive constructor:"+((archive!=null) + if (archive==null || (archive!=null && !(archive.getParentFile().canWrite() && (!archive.exists() || archive.canWrite())))) { + log.fatal("Expect Badness! -- Invalid parameters for VamsasArchive constructor:"+((archive!=null) ? "File cannot be overwritten." : "Null Object not valid constructor parameter")); + return; } + this.vamsasdocument = vamsasdocument; - if (archive.exists()) { + if (archive.exists() && !overwrite) { this.original = archive; + if (extantLock!=null) + this.odoclock = extantLock; + else + this.odoclock = new SessionFile(archive); + odoclock.lockFile(); // lock the file *immediatly* this.archive = null; // archive will be a temp file when the open method is called virginArchive=false; try { @@ -103,92 +218,31 @@ public class VamsasArchive { } else { this.original = null; this.archive = archive; // archive is written in place. + if (extantLock!=null) + rchive=extantLock; + else + rchive = new SessionFile(archive); + rchive.lockFile(); + rchive.fileLock.rafile.setLength(0); // empty the archive. 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; - - private void makeBackup() { - if (!virginArchive) { - if (originalBackup==null && original!=null && original.exists()) { - try { - accessOriginal(); - originalBackup = odoclock.backupSessionFile(null, original.getName(), ".bak", original.getParentFile()); - } - catch (IOException e) { - log.warn("Problem whilst making a backup of original archive.",e); - } - } - } - } - - /** - * called after archive is written to put file in its final place - * TODO: FINISH ?? original should have sessionFile, and archive should also have sessionFile - */ - private void updateOriginal() { - 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; - } - // 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); - } - catch (IOException e) { - log.error("Problem updating archive from temporary file! - backup in '" - +backupFile().getAbsolutePath()+"'",e); - } - } else { - // don't need to do anything. - } + this.openArchive(); // open archive } /** - * called by app to get name of backup if it was made. - * @return null or a valid file object + * open original archive file for exclusive (locked) reading. + * @throws IOException */ - public File backupFile() { - - if (!virginArchive) { - makeBackup(); - return ((original!=null) ? originalBackup : null); + private void accessOriginal() throws IOException { + if (original!=null && original.exists()) { + if (odoclock==null) + odoclock = new SessionFile(original); + odoclock.lockFile(); + if (odoc == null) + odoc = new VamsasArchiveReader(original); } - return null; - } - /** - * - * @return JarEntry name for the vamsas XML stream in this archive - */ - protected String getDocumentJarEntry() { - if (vamsasdocument) - return VamsasArchiveReader.VAMSASDOC; - return VamsasArchiveReader.VAMSASXML; } /** - * @return true if Vamsas Document has been written to archive - */ - protected boolean isDocumentWritten() { - if (newarchive==null) - log.warn("isDocumentWritten() called for unopened archive."); - if (entries!=null) { - if (entries.containsKey(getDocumentJarEntry())) - return true; - } - return false; - } - /** * Add unique entry strings to internal JarEntries list. * @param entry * @return true if entry was unique and was added. @@ -214,69 +268,17 @@ public class VamsasArchive { newarchive.putNextEntry(je); return true; } - /** - * 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 + * called by app to get name of backup if it was made. + * If this is called, the caller app *must* delete the backup themselves. + * @return null or a valid file object */ - private void openArchive() throws IOException { + public File backupFile() { - if (newarchive!=null) { - log.warn("openArchive() called multiple times."); - throw new IOException("Vamsas Archive '"+archive.getAbsolutePath()+"' is already open."); - } - 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()); - } else { - if (archive.exists()) - log.warn("New archive file name already in use! Possible lock failure imminent?"); - } - - rchive = new SessionFile(archive); - rchive.lockFile(); - 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. - * @throws IOException if a document entry has already been written. - */ - public PrintWriter getDocumentOutputStream() throws IOException { - if (newarchive==null) - openArchive(); - if (!isDocumentWritten()) { - try { - if (addValidEntry(getDocumentJarEntry())) - return new PrintWriter(new java.io.OutputStreamWriter(newarchive, "UTF-8")); - } catch (Exception e) { - log.warn("Problems opening XML document JarEntry stream",e); - } - } else { - throw new IOException("Vamsas Document output stream is already written."); - } - return null; - } - /** - * Opens and returns the applicationData output stream for the appdataReference string. - * @param appdataReference - * @return Output stream to write to - * @throws IOException - */ - public AppDataOutputStream getAppDataStream(String appdataReference) throws IOException { - if (newarchive==null) - openArchive(); - if (addValidEntry(appdataReference)) { - return new AppDataOutputStream(newarchive); + makeBackup(); + donotdeletebackup=false; // external reference has been made. + return ((original!=null) ? originalBackup : null); } return null; } @@ -290,32 +292,22 @@ public class VamsasArchive { try { newarchive.close(); - } catch (Exception e) {}; + } catch (Exception e) { + log.debug("Whilst closing newarchive",e); + }; if (!virginArchive) { // then there is something to recover. - if (originalBackup!=null) { - // backup has been made. - // revert from backup and delete it (changing backup filename) - if (rchive==null) { - rchive = new SessionFile(original); - } - SessionFile bckup = new SessionFile(originalBackup); - - 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; - } + try { + recoverBackup(); + } + catch (Exception e) { + log.warn("Problems when trying to cancel Archive "+archive.getAbsolutePath(), e); + return false; } } + } else { - log.info("cancelArchive called before archive("+original.getAbsolutePath()+") has been opened!"); + log.warn("Client Error: cancelArchive called before archive("+original.getAbsolutePath()+") has been opened!"); } closeAndReset(); // tidy up and release locks. return true; @@ -328,7 +320,7 @@ public class VamsasArchive { private void closeAndReset() { if (rchive!=null) { rchive.unlockFile(); - rchive = null; + rchive=null; } if (original!=null) { if (odoc!=null) { @@ -342,27 +334,259 @@ public class VamsasArchive { odoclock = null; } } + removeBackup(); newarchive=null; original=null; entries=null; } - - private final int _TRANSFER_BUFFER=4096*4; /** - * open original archive file for exclusive (locked) reading. - * @throws IOException + * 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() + * TODO: ensure all extant AppDataReference jar entries are transferred to new Jar + * TODO: provide convenient mechanism for generating new unique AppDataReferences and adding them to the document */ - private void accessOriginal() throws IOException { - if (original!=null && original.exists()) { - if (odoclock==null) - odoclock = new SessionFile(original); - odoclock.lockFile(); - if (odoc == null) - odoc = new VamsasArchiveReader(original); - } - } + public void closeArchive() throws IOException { + if (newarchive!=null) { + newarchive.closeEntry(); + if (!isDocumentWritten()) + log.warn("Premature closure of archive '"+archive.getAbsolutePath()+"': No document has been written."); + newarchive.close(); + updateOriginal(); + closeAndReset(); + } else { + log.warn("Attempt to close archive that has not been opened for writing."); + } + } + /** + * Opens and returns the applicationData output stream for the appdataReference string. + * @param appdataReference + * @return Output stream to write to + * @throws IOException + */ + public AppDataOutputStream getAppDataStream(String appdataReference) throws IOException { + if (newarchive==null) + throw new IOException("Attempt to write to closed VamsasArchive object."); + if (addValidEntry(appdataReference)) { + return new AppDataOutputStream(newarchive); + } + return null; + } + + /** + * + * @return JarEntry name for the vamsas XML stream in this archive + */ + protected String getDocumentJarEntry() { + if (vamsasdocument) + return VamsasArchiveReader.VAMSASDOC; + return VamsasArchiveReader.VAMSASXML; + } + /** + * Safely initializes the VAMSAS XML document Jar Entry. + * @return Writer to pass to the marshalling function. + * @throws IOException if a document entry has already been written. + */ + public PrintWriter getDocumentOutputStream() throws IOException { + if (newarchive==null) + openArchive(); + if (!isDocumentWritten()) { + try { + if (addValidEntry(getDocumentJarEntry())) + return new PrintWriter(new java.io.OutputStreamWriter(newarchive, "UTF-8")); + } catch (Exception e) { + log.warn("Problems opening XML document JarEntry stream",e); + } + } else { + throw new IOException("Vamsas Document output stream is already written."); + } + return null; + } /** + * 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; + } + /** + * returns original document's root vamsas elements. + * @return + * @throws IOException + * @throws org.exolab.castor.xml.MarshalException + * @throws org.exolab.castor.xml.ValidationException + */ + public Vobject[] getOriginalRoots() throws IOException, + org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException { + return VamsasArchive.getOriginalRoots(this); + } + /** + * @return original document or a new empty document (with default provenance) + * @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 { + return getVamsasDocument("org.vamsas.simpleclient.VamsasArchive", "Created new empty document", null); + } + /** + * Return the original document or a new empty document with initial provenance entry. + * @param provenance_user (null sets user to be the class name) + * @param provenance_action (null sets action to be 'created new document') + * @param version (null means use latest version) + * @return (original document or a new vamsas document with supplied provenance and version info) + * @throws IOException + * @throws org.exolab.castor.xml.MarshalException + * @throws org.exolab.castor.xml.ValidationException + */ + public VamsasDocument getVamsasDocument(String provenance_user, String provenance_action, String version) throws IOException, + org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException { + if (_doc!=null) + return _doc; + _doc = getOriginalVamsasDocument(this, getVorba()); + if (_doc!=null) + return _doc; + // validate parameters + if (provenance_user==null) + provenance_user = "org.vamsas.simpleclient.VamsasArchive"; + if (provenance_action == null) + provenance_action="Created new empty document"; + if (version==null) + version = VersionEntries.latestVersion(); + // Create a new document and return it + _doc = DocumentStuff.newVamsasDocument(new VAMSAS[] { new VAMSAS()}, + ProvenanceStuff.newProvenance(provenance_user, provenance_action), version); + return _doc; + } + /** + * @return Returns the current VorbaIdFactory for the archive. + */ + public VorbaIdFactory getVorba() { + if (vorba==null) + vorba = new SimpleDocument("simpleclient.VamsasArchive"); + return vorba.getVorba(); + } + /** + * @return true if Vamsas Document has been written to archive + */ + protected boolean isDocumentWritten() { + if (newarchive==null) + log.warn("isDocumentWritten() called for unopened archive."); + if (entries!=null) { + if (entries.containsKey(getDocumentJarEntry())) + return true; + } + return false; + } + private void makeBackup() { + if (!virginArchive) { + if (originalBackup==null && original!=null && original.exists()) { + try { + accessOriginal(); + originalBackup = odoclock.backupSessionFile(null, original.getName(), ".bak", original.getParentFile()); + } + catch (IOException e) { + log.warn("Problem whilst making a backup of original archive.",e); + } + } + } + } + /** + * 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. + * @param doclock TODO + * @throws IOException + */ + private void openArchive() throws IOException { + + if (newarchive!=null) { + log.warn("openArchive() called multiple times."); + throw new IOException("Vamsas Archive '"+archive.getAbsolutePath()+"' is already open."); + } + 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()); + } else { + if (archive.exists()) + log.warn("New archive file name already in use! Possible lock failure imminent?"); + } + + if (rchive==null) + rchive = new SessionFile(archive); + if (!rchive.lockFile()) + throw new IOException("Failed to get lock on file "+archive); + newarchive = new JarOutputStream(new BufferedOutputStream(new java.io.FileOutputStream(archive))); + entries = new Hashtable(); + } + public void putVamsasDocument(VamsasDocument doc) throws IOException, + org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException { + putVamsasDocument(doc, getVorba()); + } + + public void putVamsasDocument(VamsasDocument doc, VorbaIdFactory vorba) throws IOException, + org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException { + VorbaXmlBinder.putVamsasDocument(getDocumentOutputStream(), vorba, doc); + } + + /** + * recovers the original file's contents from the (temporary) backup. + * @throws Exception if any SessionFile or file removal operations fail. + */ + private void recoverBackup() throws Exception { + if (originalBackup!=null) { + // backup has been made. + // revert from backup and delete it (changing backup filename) + if (rchive==null) { + rchive = new SessionFile(original); + } + SessionFile bckup = new SessionFile(originalBackup); + + rchive.updateFrom(null, bckup); // recover from backup file. + bckup.unlockFile(); + bckup=null; + removeBackup(); + } + } + + /** + * forget about any backup that was made - removing it first if it was only temporary. + */ + private void removeBackup() { + if (originalBackup!=null) { + log.debug("Removing backup in "+originalBackup.getAbsolutePath()); + if (!donotdeletebackup) + if (!originalBackup.delete()) + log.info("VamsasArchive couldn't remove temporary backup "+originalBackup.getAbsolutePath()); + originalBackup=null; + } + } + /** + * @param vorba the VorbaIdFactory to use for accessing vamsas objects. + */ + public void setVorba(VorbaIdFactory Vorba) { + if (Vorba!=null) { + if (vorba==null) + vorba = new SimpleDocument(Vorba); + else + vorba.setVorba(Vorba); + } else + getVorba(); + } + /** * 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 * entry doesn't exist in the backed-up original. @@ -374,6 +598,7 @@ public class VamsasArchive { 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) @@ -420,208 +645,67 @@ public class VamsasArchive { +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() - * TODO: ensure all extant AppDataReference jar entries are transferred to new Jar - * TODO: provide convenient mechanism for generating new unique AppDataReferences and adding them to the document - */ - public void closeArchive() throws IOException { - if (newarchive!=null) { - newarchive.closeEntry(); - if (!isDocumentWritten()) - log.warn("Premature closure of archive '"+archive.getAbsolutePath()+"': No document has been written."); - newarchive.close(); - updateOriginal(); - closeAndReset(); - } else { - 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. + * transfers any AppDataReferences existing in the old document + * that haven't already been transferred to the new one + * TODO: LATER: do the same for transfers requiring a namechange - more document dependent. + * @return true if data was transferred. */ - public VamsasArchiveReader getOriginalArchiveReader() throws IOException { - if (!virginArchive) { - accessOriginal(); - return odoc; + public boolean transferRemainingAppDatas() throws IOException { + boolean transfered=false; + if (original==null || !original.exists()) { + log.warn("No backup archive exists."); + return false; } - return null; - } - /** - * returns original document's root vamsas elements. - * @return - * @throws IOException - * @throws org.exolab.castor.xml.MarshalException - * @throws org.exolab.castor.xml.ValidationException - */ - public object[] getOriginalRoots() throws IOException, - org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException { - return VamsasArchive.getOriginalRoots(this); - } - /** - * 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(); - // TODO ensure embedded appDatas are garbage collected to save memory - } 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; + accessOriginal(); + + if (getVorba()!=null) { + Vector originalRefs=null; + try { + originalRefs = vorba.getReferencedEntries(getVamsasDocument(), getOriginalArchiveReader()); + } catch (Exception e) { + log.warn("Problems accessing original document entries!",e); + } + if (originalRefs!=null) { + Iterator ref = originalRefs.iterator(); + while (ref.hasNext()) { + String oldentry = (String) ref.next(); + if (oldentry!=null && !entries.containsKey(oldentry)) { + log.debug("Transferring remaining entry '"+oldentry+"'"); + transfered |= transferAppDataEntry(oldentry); + } } } - } - return null; - } - protected VorbaIdFactory vorba = null; - - /** - * @return Returns the current VorbaIdFactory for the archive. - */ - public VorbaIdFactory getVorba() { - return vorba; + } + return transfered; } - /** - * @param vorba the VorbaIdFactory to use for accessing vamsas objects. - */ - public void setVorba(VorbaIdFactory vorba) { - this.vorba = vorba; - } - - /** - * 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, getVorba()); - 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 + * called after archive is written to put file in its final place */ - public static VamsasDocument getOriginalVamsasDocument(VamsasArchive ths) throws IOException, - org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException { - return VamsasArchive.getOriginalVamsasDocument(ths, null); - } - private VorbaIdFactory makeDefaultFactory(VorbaIdFactory vorba) { - if (vorba==null) { - vorba = getVorba(); - if (vorba==null) { - vorba = IdFactory.getDummyFactory("simpleclient.VamsasArchive"); - setVorba(vorba); // save for later use + private void updateOriginal() { + 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; } - } - return vorba; - } - /** - * Uses VorbaXmlBinder to retrieve the VamsasDocument from the original archive referred to by ths - * @param ths - * @param vorba - * @return - * @throws IOException - * @throws org.exolab.castor.xml.MarshalException - * @throws org.exolab.castor.xml.ValidationException - */ - public static VamsasDocument getOriginalVamsasDocument(VamsasArchive ths, VorbaIdFactory vorba) throws IOException, - org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException { - VamsasArchiveReader oReader = ths.getOriginalArchiveReader(); - if (oReader!=null) { - // check the factory - vorba = ths.makeDefaultFactory(vorba); - if (oReader.isValid()) { - InputStreamReader vdoc = new InputStreamReader(oReader.getVamsasDocumentStream()); - Object unmarsh[] = VorbaXmlBinder.getVamsasObjects(vdoc, vorba, new VamsasDocument()); - if (unmarsh==null) - log.fatal("Couldn't unmarshall document!"); - - object[] vobjs = (object[]) unmarsh[0]; - if (vobjs!=null) { - VamsasDocument doc=(VamsasDocument) vobjs[0]; - if (doc!=null) - return doc; - } - log.debug("Found no VamsasDocument object in properly formatted Vamsas Archive."); - } 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); - Object unmarsh[] = VorbaXmlBinder.getVamsasObjects(vxml, vorba, new VAMSAS()); - - if (unmarsh==null) - log.fatal("Couldn't unmarshall document!"); - - VAMSAS root[]= new VAMSAS[] { null}; - root[0] = (VAMSAS) unmarsh[0]; - - if (root[0]==null) { - log.debug("Found no VAMSAS object in VamsasXML stream."); - } else { - log.debug("Making new VamsasDocument from VamsasXML stream."); - 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 " - // TODO: VAMSAS: decide on machine readable info embedding in provenance should be done - +ths.original+""), VersionEntries.ALPHA_VERSION); - root[0]=null; - root=null; - return doc; - } - } + // Make a backup if it isn't done already + makeBackup(); + try { + // copy new Archive data that was writen to a temporary file + odoclock.updateFrom(null, rchive); } + catch (IOException e) { + // TODO: LATER: decide if leaving nastily named backup files around is necessary. + log.error("Problem updating archive from temporary file! - backup left in '" + +backupFile().getAbsolutePath()+"'",e); + } + // Tidy up if necessary. + removeBackup(); + } else { + } - // otherwise - there was no valid original document to read. - return null; - } - public void putVamsasDocument(VamsasDocument doc) throws IOException, - org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException { - VorbaIdFactory vorba = makeDefaultFactory(null); - VorbaXmlBinder.putVamsasDocument(getDocumentOutputStream(), vorba, doc); } }