+++ /dev/null
-/**
- *
- */
-package org.vamsas.client.simpleclient;
-
-import java.io.DataInput;
-import java.io.DataInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.jar.JarInputStream;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * @author jimp
- * LATER: this may not be a necessary or useful class to return from IClientAppdata get*InputStream() methods
- */
-public class AppDataInputStream extends DataInputStream implements DataInput {
- private Log log = LogFactory.getLog(AppDataInputStream.class);
- private boolean isOpen = false;
- /**
- * Wrapper for writing to/from AppData Entries in a Vamsas Document.
- */
- public AppDataInputStream(InputStream inputstream) {
- super(inputstream);
- isOpen=true;
- }
-
- /* (non-Javadoc)
- * @see java.io.FilterInputStream#close()
- */
- public void close() throws IOException {
- if (!isOpen) {
- log.debug("close() called on closed AppDataInputStream.");
- // throw new IOException("Attempt to close an already closed AppDataInputStream");
- } else {
- isOpen=false;
- }
- }
-
- /**
- * Will return zero if stream has been closed.
- * @see java.io.FilterInputStream#available()
- */
- public int available() throws IOException {
- if (isOpen)
- return super.available();
- else
- return 0;
- }
-
-}
+++ /dev/null
-/**
- *
- */
-package org.vamsas.client.simpleclient;
-
-import java.io.DataOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * @author jimp
- *
- */
-public class AppDataOutputStream extends DataOutputStream {
- private Log log = LogFactory.getLog(AppDataOutputStream.class);
- private boolean isOpen=true;
- /**
- * @param out
- */
- public AppDataOutputStream(OutputStream out) {
- super(out);
- isOpen=true;
- }
- /* (non-Javadoc)
- * @see java.io.DataOutputStream#flush()
- */
- public void flush() throws IOException {
- if (isOpen)
- super.flush();
- else
- log.warn("flush() called on closed AppDataOutputStream");
- }
- /* (non-Javadoc)
- * @see java.io.DataOutputStream#write(byte[], int, int)
- */
- public synchronized void write(byte[] b, int off, int len) throws IOException {
- if (isOpen) {
- super.write(b, off, len);
- } else {
- log.debug("write(b,off,len) called on closed AppDataOutputStream");
- throw new IOException("Attempt to write to closed AppDataOutputStream");
- }
- }
- /* (non-Javadoc)
- * @see java.io.DataOutputStream#write(int)
- */
- public synchronized void write(int b) throws IOException {
- if (isOpen) {
- super.write(b);
- } else {
- log.debug("write(b) called on closed AppDataOutputStream");
- throw new IOException("Attempt to write to closed AppDataOutputStream");
- }
- }
- /**
- * Sets an internal flag preventing further write operations
- * to the AppData output stream and flushes any pending writes.
- * @see java.io.FilterOutputStream#close()
- */
- public void close() throws IOException {
- isOpen=false;
- super.flush();
- log.debug("AppDataOutputStream was closed.");
- }
- /* (non-Javadoc)
- * @see java.io.FilterOutputStream#write(byte[])
- */
- public void write(byte[] b) throws IOException {
- if (isOpen) {
- super.write(b);
- } else {
- log.debug("write(b[]) called on closed AppDataOutputStream");
- throw new IOException("Attempt to write to closed AppDataOutputStream");
- }
- }
- /**
- * @return true if stream is still Open.
- */
- public boolean isOpen() {
- return isOpen;
- }
-
-}
+++ /dev/null
-package org.vamsas.client.simpleclient;
-
-import java.io.File;
-import java.net.MalformedURLException;
-
-/**
- * Vamsas Document URN for files understood by ArchiveReader and
- * written by VamsasArchive.
- * vdoc://{Absolute path to file}
- * @author jimp
- *
- */
-public class ArchiveUrn extends org.vamsas.client.SessionUrn {
- /**
- * a simple vamsas document urn prefix
- */
- public static String VAMSASDOCUMENT="vdoc";
- static {
- TYPES.put(ArchiveUrn.VAMSASDOCUMENT, ArchiveUrn.class);
- }
-
- public ArchiveUrn(File docLocation) throws MalformedURLException {
- super(VAMSASDOCUMENT, docLocation.getAbsoluteFile().toURL());
- }
-
- /**
- * TODO: LATER: think about this again.
- * @return File(urn.getPath())
- */
- public File asFile() {
- return new File(urn.getPath());
- }
- // TODO: add abstract 'handler' methods for resolving the URN to a particular class
-}
+++ /dev/null
-/*
- *
- */
-package org.vamsas.client.simpleclient;
-
-import java.io.IOException;
-import java.util.Vector;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.vamsas.client.ClientHandle;
-import org.vamsas.client.IClientAppdata;
-import org.vamsas.client.IClientDocument;
-import org.vamsas.client.UserHandle;
-import org.vamsas.client.Vobject;
-import org.vamsas.client.VorbaId;
-import org.vamsas.objects.core.ApplicationData;
-import org.vamsas.objects.core.User;
-import org.vamsas.objects.core.VAMSAS;
-import org.vamsas.objects.core.VamsasDocument;
-import org.vamsas.objects.utils.AppDataReference;
-import org.vamsas.test.objects.Core;
-
-/**
- * Maintains a collection of vamsas objects, appdatas and states, and provides api for a SimpleClient's client.
- * @author jimp
- */
-public class ClientDocument extends org.vamsas.client.ClientDocument implements IClientDocument {
- private static Log log = LogFactory.getLog(ClientDocument.class);
- private VamsasDocument doc;
- protected SimpleClient sclient;
- protected VamsasArchive archive = null;
- /**
- * indicate if new data has been incorporated
- */
- private boolean isModified = false;
- /**
- * Public method for internal use by SimpleClient.
- * @return true if document has been modified.
- */
- public boolean isModified() {
- return isModified;
- }
- private Vector updatedObjects=null;
- /**
- *
- * prepare Application-side dataset from the vamsas Document archive
- * @param doc - the dataset
- * @param docHandler - the sessionFile IO handler
- * @param Factory - the source of current and new vorbaIds
- * @param sclient - the simpleclient instance
- */
- protected ClientDocument(VamsasDocument doc, VamsasArchive docHandler, IdFactory Factory, SimpleClient sclient) {
- super(Factory.getVorbaIdHash(), Factory);
-
-
- /**
- * prepare Application-side dataset from the vamsas Document archive
- */
- this.sclient = sclient;
- archive = docHandler;
- this.doc = doc;
- updatedObjects=null; /// TODO: correct this line
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.vamsas.client.IClientDocument#getObject(org.vamsas.client.VorbaId)
- */
- public Vobject getObject(VorbaId id) {
- if (vamsasObjects==null) {
- log.debug("getObject called on null objrefs list.");
- return null;
- }
- if (vamsasObjects.containsKey(id))
- return (Vobject) vamsasObjects.get(id);
- log.debug("Returning null Vobject reference for id "+id.getId());
- return null;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.vamsas.client.IClientDocument#getObjects(org.vamsas.client.VorbaId[])
- */
- public Vobject[] getObjects(VorbaId[] ids) {
- if (vamsasObjects==null) {
- log.debug("getObject[] called on null vamsasObjects list.");
- return null;
- }
- Vobject[] vo = new Vobject[ids.length];
- for (int i=0,j=ids.length; i<j;i++)
- if (vamsasObjects.containsKey(ids[i]))
- vo[i] = (Vobject) vamsasObjects.get(ids[i]);
- else
- log.debug("Returning null Vobject reference for id "+ids[i].getId());
- return vo;
- }
- /**
- * internal reference to single copy of Document Roots array
- */
- private VAMSAS[] _VamsasRoots=null;
- /*
- * (non-Javadoc)
- * LATER: currently there is only one Vector of roots ever passed to client - decide if this is correct (means this is not thread safe and may behave unexpectedly)
- * @see org.vamsas.client.IClientDocument#getVamsasRoots()
- */
- public VAMSAS[] getVamsasRoots() {
- if (doc==null) {
- log.debug("Null document for getVamsasRoots(), returning null");
- return null;
- }
- if (archive==null) {
- // LATER: decide on read-only status of ClientDocument object
- log.warn("getVamsasRoots() called on possibly read-only document.");
- }
- if (_VamsasRoots!=null)
- return _VamsasRoots;
- VAMSAS[] roots = doc.getVAMSAS();
- if (roots == null) {
- // Make a new one to return to client to get filled.
- _VamsasRoots = new VAMSAS[] { new VAMSAS() };
- // Do provenance now. just in case.
- doc.getProvenance().addEntry(sclient.getProvenanceEntry("Created new document root [id="+_VamsasRoots[0].getId()+"]"));
- doc.addVAMSAS(_VamsasRoots[0]);
- } else {
- _VamsasRoots = new VAMSAS[roots.length];
- for (int r=0;r<roots.length; r++)
- _VamsasRoots[r] = roots[r];
- }
- return _VamsasRoots;
- }
-
- private int _contains(VAMSAS root, VAMSAS[] docRoots) {
- if (root==null)
- return -1;
- if (docRoots==null || docRoots.length==0)
- return -1;
- String r_id = root.getId();
- for (int i=0,j=docRoots.length; i<j; i++)
- if (docRoots[i]==root || (docRoots[i]!=null && docRoots[i].getId().equals(r_id)))
- return i;
- return -1;
- }
-/**
- * verify that newr version is really an intact version of the
- * @param newVersion (may be modified)
- * @param oldVersion
- * @return true if newVersion is a valid root that preserves original references
- */
- private boolean isValidUpdate(VAMSAS newVersion, final VAMSAS oldVersion) {
- // ideal - this cascades down the two structures, ensuring that all ID'd objects in one are present in the other.
- if (oldVersion==newVersion) {
- // may be a virgin root element.
- if (!newVersion.isRegistered())
- _registerObject(newVersion);
- // Should retrieve original version and compare - unless local hashes can be used to determine if resultSet has been truncated.
- // just do internal validation for moment.
- if (newVersion.isValid())
- return true;
- return false;
- } else {
- // redundant ? if (oldVersion.is__stored_in_document())
- if (!newVersion.isRegistered())
- _registerObject(newVersion);
- if (newVersion.isValid())
- return true;
- }
- return false;
- /**
- * LATER isValidUpdate : Ideally. we efficiently walk down, comparing hashes, to deal with merging and verifying provenance for objects
-
- // extract root objects
- if (newroots != null) {
- // check newroots for objects that were present in the old document
- // check to see if the 'old' objects have been modified
- // if they have ? we overwrite them with their new version, ensuring that
- // provenance is updated.
- // if they haven't ? do nothing ?
-
- for (int i = 0, k = newroots.length; i < k; i++) {
- if (newroots[i].isRegistered()) {
- // easy - just check if anything has changed and do provenance
- Vobject oldversion = getObject(newroots[i].getVorbaId());
- if (oldversion instanceof VAMSAS) {
- // LATER: appropriate merging behaviour when two clients have improperly modified the same Vobject independently.
- if (newroots[i].get__last_hash() != newroots[i].hashCode()) {
- // client has modified this Vobject since last retrieval.
- if (newroots[i].get__last_hash() != oldversion.get__last_hash()) {
- // Vobject has been modified by another client since this
- // client's
- // last access to document.
- }
- }
- } else {
- throw new Error(
- "SimpleClient error when using setVamsasRoots : The vorbaId for Vobject "
- + i
- + " does not refer to an Vobject of type VAMSAS in the current document!");
- }
- } else {
- if (!newroots[i].is__stored_in_document()) {
- // check if Vobject is modified
- if (newroots[i].get__last_hash() != newroots[i].hashCode()) {
- // it is - so we add newroots[i] as a new Vobject, with updated
- // provenance.
- } else {
- // do nothing
- newroots[i] = null;
- }
- } else {
- // just add newroots[i] as a new Vobject in the document
- // - with appropriate provenance.
- }
- }
- }*/
- }
- /**
- * merge old and new root vectors
- * @param newr This array may be written to
- * @param original
- * @param the client document (usually this) which this root set belongs to.
- * @return merged vector of vamsas roots
- */
- private VAMSAS[] _combineRoots(VAMSAS[] newr, final VAMSAS[] original, ClientDocument modflag) {
- Vector rts = new Vector();
- boolean modified=false;
- for (int i=0,j=original.length; i<j; i++) {
- int k = _contains(original[i], newr);
- if (k>-1) {
- if (isValidUpdate(newr[k], original[i])) {
- modified=true;
- rts.add(newr[k]);
- newr[k]=null;
- } else {
- // LATER: try harder to merge ducument roots.
- log.warn("Couldn't merge new VAMSAS root "+newr[k].getId());
- newr[k] = null; // LATER: this means we ignore mangled roots. NOT GOOD
- }
- } else {
- // add in order.
- rts.add(original[i]);
- }
- }
- // add remaining (new) roots
- for (int i=0,j=newr.length; i<j; i++) {
- if (newr[i]!=null) {
- rts.add(newr[i]);
- modified=true;
- }
- }
- newr = new VAMSAS[rts.size()];
- for (int i=0,j=rts.size(); i<j; i++)
- newr[i] = (VAMSAS) rts.get(i);
- if (modflag!=null)
- modflag.isModified = modified;
- return newr;
- }
-
- /**
- * update the document with new roots.
- * LATER: decide: this affects the next call to getVamsasRoots()
- * @see org.vamsas.IClientDocument.setVamsasRoots
- */
- public void setVamsasRoots(VAMSAS[] newroots) {
- if (doc==null) {
- log.debug("setVamsasRoots called on null document.");
- return;
- }
- VAMSAS[] newr;
- if (newroots==null) {
- log.debug("setVamsasRoots(null) - do nothing.");
- return;
- }
- // are we dealing with same array ?
- if (_VamsasRoots!=newroots) {
- // merge roots into local version.
- newr = new VAMSAS[newroots.length];
- for (int i=0;i<newr.length;i++)
- newr[i] = newroots[i];
- newr=_combineRoots(newr,_VamsasRoots,this);
- } else {
- newr = new VAMSAS[_VamsasRoots.length];
- for (int i=0;i<newr.length;i++)
- newr[i]=_VamsasRoots[i];
- }
- // actually compare with document root set for final combination (to ensure nothing is lost)
- _VamsasRoots = _combineRoots(newr, doc.getVAMSAS(), this);
- }
-
-
- /* (non-Javadoc)
- * LATER: decide: this affects the next call to getVamsasRoots()
- * @see org.vamsas.client.IClientDocument#addVamsasRoot(org.vamsas.objects.core.VAMSAS)
- */
- public void addVamsasRoot(VAMSAS newroot) {
- if (doc==null) {
- log.debug("addVamsasRoots called on null document.");
- return;
- }
- VAMSAS[] newroots = _combineRoots(new VAMSAS[] {newroot}, _VamsasRoots, this);
- _VamsasRoots = newroots;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.vamsas.client.IClientDocument#registerObjects(org.vamsas.client.Vobject[])
- */
- public VorbaId[] registerObjects(Vobject[] unregistered) {
- if (doc==null) {
- log.warn("registerObjects[] called on null document.");
- return null;
- }
- if (vamsasObjects==null) {
- log.warn("registerObjects[] called for null vamsasObjects hasharray.");
- return null;
- }
- if (unregistered!=null) {
- VorbaId ids[] = new VorbaId[unregistered.length];
- for (int i=0,k=unregistered.length; i<k; i++)
- if (unregistered[i]!=null) {
- log.warn("Null Vobject passed to registerObject[] at position "+i);
- return null;
- } else {
- ids[i]=registerObject(unregistered[i]);
- }
- log.debug("Registered "+unregistered.length+" objects - total of "+vamsasObjects.size()+" ids.");
- return ids;
- }
- return null;
- }
- /* (non-Javadoc)
- * @see org.vamsas.client.IClientDocument#registerObject(org.vamsas.client.Vobject)
- */
- public VorbaId registerObject(Vobject unregistered) {
- if (doc==null) {
- log.warn("registerObjects called on null document.");
- return null;
- }
- if (vamsasObjects==null) {
- log.warn("registerObjects called for null vamsasObjects hasharray.");
- return null;
- }
- if (unregistered!=null) {
- VorbaId id = _registerObject(unregistered);
- log.debug("Registered object - total of "+vamsasObjects.size()+" ids.");
- return id;
- }
- log.warn("Null Vobject passed to registerObject.");
- return null;
- }
- /**
- * IClientAppdata instance - if it exists.
- */
- SimpleClientAppdata scappd = null;
- /* (non-Javadoc)
- * @see org.vamsas.client.IClientDocument#getClientAppdata()
- */
- public IClientAppdata getClientAppdata() {
- if (doc==null) {
- log.warn("getClientAppdata called on null document.");
- return null;
- }
- if (scappd==null) {
- log.debug("Creating new SimpleClientAppdata instance for "+sclient.getSessionHandle());
- scappd = new SimpleClientAppdata(this);
- if (scappd==null) {
- // LATER: may not need this as a warning message.
- log.warn("Null appdata object for "+sclient.getSessionHandle());
- } else {
- log.debug("Created SimpleClientAppdata successfully.");
- }
- } else {
- log.debug("Returning existing SimpleClientAppdata reference.");
- }
- return scappd;
- }
- /**
- * access the vamsas document
- * @return the session's vamsas document
- */
- protected VamsasDocument getVamsasDocument() {
- return doc;
- }
- /**
- * returns the read-only IO interface for the vamsas document Jar file
- * @return
- */
- protected VamsasArchiveReader getVamsasArchiveReader() {
- try {
- return archive.getOriginalArchiveReader();
- } catch (Exception e) {
- log.warn("Unable to create OriginalArchiveReader!", e);
- }
- return null;
- }
- protected boolean updateSessionDocument() throws java.io.IOException {
- boolean docupdate = true; // 'non-serious' problems below set this false
- if (doc==null) {
- log.warn("updateSessionDocument called on null document.");
- throw new java.io.IOException("Document is closed.");
- }
- if (archive==null) {
- log.warn("updateSessionDocument called document archive handler.");
- throw new java.io.IOException("Document is closed.");
- }
-
- if (!isModified() && !scappd.isModified()) {
- log.debug("Document update not necessary. returning false.");
- return false;
- }
- VamsasSession session = sclient._session;
- log.debug("updating Session Document in "+session.sessionDir);
- // update the VamsasDocument structure with any new appData's.
- // try to update the sessionFile
- log.debug("Attempting to update session "+sclient.session.getSessionUrn());
- if (scappd.isModified()) {
- ClientHandle client = sclient.client;
- UserHandle user = sclient.user;
- scappd.closeForWriting();
- if (scappd.appsGlobal==null) {
- log.debug("Creating new appData entry for this application...");
- // first write for this application - add a new section in document
- ApplicationData appd = scappd.appsGlobal = new ApplicationData();
- appd.setName(client.getClientName());
- // appd.setUrn(client.getClientUrn());
- appd.setVersion(client.getVersion());
- doc.addApplicationData(appd);
- // embed or jarEntry ? - for now only jarEntry's are dealt with.
- appd.setDataReference(AppDataReference.uniqueAppDataReference(doc, sclient.client.getClientUrn()));
- log.debug("... created.");
- }
- if (scappd.newAppData!=null && scappd.newAppData.sessionFile.exists()) {
- log.debug("Beginning update for new Global Appdata...");
- // new global appdata to write.
- if (scappd.appsGlobal.getData()!=null) {
- scappd.appsGlobal.setData(null);
- scappd.appsGlobal.setDataReference(AppDataReference.uniqueAppDataReference(doc, sclient.client.getClientUrn()));
- }
- // LATER: use a switch to decide if the data should be written as a reference or as an embedded data chunk
- scappd.updateAnAppdataEntry(archive, scappd.appsGlobal, scappd.newAppData);
- log.debug("...Successfully updated Global Appdata Entry.");
- }
- if (scappd.newUserData!=null && scappd.newUserData.sessionFile.exists()) {
- log.debug("Beginning to update Users Appdata entry....");
- if (scappd.usersData==null) {
- // create new user appdata
- scappd.usersData = new User();
- scappd.usersData.setFullname(user.getFullName());
- scappd.usersData.setOrganization(user.getOrganization());
- scappd.appsGlobal.addUser(scappd.usersData);
- }
- User appd = scappd.usersData;
- if (appd.getData()!=null || appd.getDataReference()==null) {
- // LATER make standard appDataReference constructor for client+user
- appd.setData(null);
- String safe_username = user.getFullName();
- int t = safe_username.indexOf(" ");
- if (t!=-1) {
- safe_username = safe_username.substring(t);
- }
- appd.setDataReference(AppDataReference.uniqueAppDataReference(doc, sclient.client.getClientUrn()+safe_username));
- }
- scappd.updateAnAppdataEntry(archive, scappd.usersData, scappd.newUserData);
- log.debug("...Successfully updated user AppData entry.");
- }
- }
- log.debug("Updating Document...");
- // now update the document.
- try {
- archive.putVamsasDocument(doc);
- log.debug("Successfully written document entry.");
- }
- catch (Exception e) {
- log.error("Marshalling error for vamsas document.",e);
- docupdate = false; // pass on the (probable) object validation error
- }
- if (archive.transferRemainingAppDatas())
- log.debug("Remaining appdatas were transferred.");
- else
- log.debug("No remaining appdatas were transferred. (Correct?)");
- archive.closeArchive();
- log.debug("...successully finished and closed.");
- return docupdate; // no errors ?
- }
- /* (non-Javadoc)
- * @see java.lang.Object#finalize()
- */
- protected void finalize() throws Throwable {
- log.debug("Garbage collecting on ClientDocument instance.");
- if (scappd!=null) {
- scappd.finalize();
- scappd = null;
- }
- if (doc!=null) {
- doc = null;
- }
- // disengage from client
- if (sclient!=null)
- sclient.cdocument = null;
- sclient=null;
-
- super.finalize();
- }
- public Vector getUpdatedObjects() {
- return updatedObjects;
- }
-}
+++ /dev/null
-package org.vamsas.client.simpleclient;
-
-import org.vamsas.client.*;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStreamReader;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutput;
-import java.io.ObjectOutputStream;
-import java.io.OutputStream;
-import java.util.Vector;
-
-/**
- * Handler for the clientsFile within a vamsas session thread.
- * @author jim
- */
-public class ClientsFile extends ListFile {
- private static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(ClientsFile.class);
- /**
- * number of my client in list - passed back when a client
- * is added to list, and used (if valid) for quickly
- * looking up presence of client handle in the list.
- */
- private int syncnum = 1;
-
- public ClientsFile(File filelist) throws IOException {
- super(filelist);
- }
-
- /**
- * internal method for getting clientList - ensures a lock has been made but
- * does not release it.
- *
- * @return list of clients
- */
- private ClientHandle[] retrieveClientHandles() {
- if (lockFile()) {
- try {
- ClientHandle[] clients=null;
- if (fileLock.length()>0) {
-
- ObjectInputStream is = new ObjectInputStream(fileLock.getBufferedInputStream(true));
- Object o;
- o=is.readObject();
- if (o!=null) {
- try {
- clients = (ClientHandle[]) o;
- }
- catch (Exception e) {
- System.err.println("Garbage in the clientHandle list "+this.sessionFile);
- }
- }
- }
- return clients;
- } catch (FileNotFoundException e) {
- // TODO Auto-generated catch block
- e.printStackTrace(System.err);
- } catch (Exception e) {
- e.printStackTrace(System.err);
- }
- }
- return null;
- }
- /**
- * get the clientList from the file. May return null if lock failed!
- * @return clientList
- */
- public ClientHandle[] retrieveClientList() {
- if (lockFile()) {
- ClientHandle[] clients = retrieveClientHandles();
- 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 ClientHandle[] retrieveClientList(Lock extantlock) {
- if (lockFile(extantlock)) {
- ClientHandle[] clients = retrieveClientHandles();
- 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 addClient(ClientHandle me, Lock extantLock) {
- return addClient(me, true, extantLock);
- }
-
- /**
- * adds clientHandle me to the clientList under an existing lock.
- * @param me - clientHandle
- * @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 addClient(ClientHandle me, boolean disambig, Lock extantLock) {
- if (lockFile(extantLock)) {
- syncnum = addClient(me, disambig);
- unlockFile();
- return syncnum;
- }
- return 0;
- }
-
- /**
- * adds the ClientHandle to the list - if it is not unique, then the
- * ClientHandle object is modified to make it unique in the list. returns the
- * clientNumber for the client in the session.
- *
- * @param me
- * @return
- */
-
- public int addClient(ClientHandle me) {
- syncnum = addClient(me, true);
- unlockFile();
- return syncnum;
- }
-
- /**
- * removes 'me' from the session ClientList without complaint if 'me' isn't in the clientList already.
- * @param me client handle to be removed
- * @param clientlock existing lock passed from watcher.
- */
- public void removeClient(ClientHandle me, Lock clientlock) {
- int mynum=-1;
- if (lockFile(clientlock)) {
- ClientHandle[] clients = retrieveClientHandles();
- if (clients != null) {
- if ((syncnum<=0 || syncnum>clients.length) || clients[syncnum-1]!=me) {
- for (int i = 0, j = clients.length; i < j; i++)
- if (clients[i].equals(me)) {
- mynum=i;
- break;
- }
- } else {
- mynum=syncnum-1;
- }
- if (mynum>-1) {
- ClientHandle[] newlist = new ClientHandle[clients.length - 1];
- for (int k=0,i = 0, j = clients.length; i < j; i++)
- if (i!=mynum)
- newlist[k++] = clients[i];
- if (!putClientList(newlist))
- throw new Error("Failed to write new clientList!"); // failed to put the clientList to disk.
- }
- }
- unlockFile();
- } else {
- throw new Error("Couldn't get lock for "+((sessionFile==null) ? "Unitialised sessionFile in ClientsFile" : sessionFile.getAbsolutePath()));
- }
- }
- /**
- * Adds a ClientHandle to the ClientList file - optionally disambiguating
- * the ClientHandle (modifes the URN).
- * Note: Caller is left to release the lock on the ClientList.
- * @param me
- * @param disambiguate -
- * flag indicating if the URN for me should be disambiguated to
- * differentiate between sessions.
- * @return index of clientHandle in new list, or -1-position of existing
- * clientHandle (if disambiguate is true)
- */
- protected int addClient(ClientHandle me, boolean disambiguate) {
- int newclient = 0;
- int tries=5;
- while (tries-->0 && !lockFile())
- try { Thread.sleep(1); } catch (Exception e){};
- if (lockFile()) {
- ClientHandle[] clients = retrieveClientHandles();
- if (me.getClientUrn()==null) {
- // TODO: move this into ClientUrn as a standard form method.
- me.setClientUrn("vamsas://"+me.getClientName()+":"+me.getVersion()+"/");
- }
- if (clients == null) {
- clients = new ClientHandle[1];
- clients[0] = me;
- newclient = 1;
- } else {
- int k = 0;
- for (int i = 0, j = clients.length; i < j; i++) {
- if (clients[i].equals(me)) {
- if (disambiguate) {
- while (clients[i].equals(me)) {
- 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;
- ClientHandle[] newlist = new ClientHandle[clients.length + 1];
- for (i = 0, j = clients.length; i < j; i++)
- newlist[i] = clients[i];
- newlist[j] = me;
- clients = newlist;
- newclient = j+1;
- }
- if (!putClientList(clients))
- return 0; // failed to put the clientList to disk.
- }
- return newclient;
- }
- /**
- * 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;
- /**
- * safely writes clients array to the file referred to by sessionFile.
- *
- * @param clients
- * @return true if successful write. Throws Errors otherwise.
- */
- protected boolean putClientList(ClientHandle[] clients) {
- if (lockFile()) {
- File templist=null;
- if (!backup || (templist = backupSessionFile()) != null) {
- int retries=3;
- while (retries-->0) {
- try {
- ObjectOutputStream os =
- new ObjectOutputStream(fileLock.getBufferedOutputStream(true));
- log.debug("About to write "+clients.length+" clientHandles to output stream.");
- os.writeObject(clients);
- os.close();
- // All done - remove the backup.
- if (backup)
- templist.delete();
- templist = null;
- retries=-1;
- } catch (Exception e) {
- System.err
- .println("Serious - problems writing to sessionFile.");
- if (retries>0 && templist != null) {
- System.err.println("Recovering from Backup in "
- + templist.getAbsolutePath());
- templist.renameTo(fileLock.target);
- }
- e.printStackTrace(System.err);
- }
- }
- if (retries>-2) {
- System.err
- .println("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: "
- + ((sessionFile == null) ? "Unitialized ClientsFile"
- : " failed to get lock on " + sessionFile.getAbsolutePath()));
- }
- // successful!
- return true;
- }
-
- public void clearList() {
- if (lockFile()) {
- try {
- FileOutputStream fout = fileLock.getFileOutputStream(true);
- fout.flush();
- fout.close();
- } catch (Exception e) {
- throw new Error("Problems trying to clear clientlist!",e);
-
- }
- }
-
- }
-}
+++ /dev/null
-package org.vamsas.client.simpleclient;
-
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeSupport;
-import java.util.Hashtable;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.vamsas.client.Events;
-
-/**
- * monitors watcher objects and generates events.
- */
-public class EventGeneratorThread extends Thread implements Runnable {
- private static Log log = LogFactory.getLog(EventGeneratorThread.class);
- private SimpleClient client;
- private Hashtable handlers; // manager object
- private VamsasSession session;
-
- /**
- * list with all the clientHandles for the session
- */
- protected FileWatcher clientfile=null;
- /**
- * the session's vamsasDocument
- */
- protected FileWatcher vamsasfile=null;
- /**
- * written to by client when its app calls storeDocument.
- */
- protected FileWatcher storeFile=null;
-
- private boolean watch=false;
-
-
- EventGeneratorThread(VamsasSession s, SimpleClient _client, Hashtable eventhandlers) {
- if (eventhandlers==null || s==null || _client==null)
- throw new Error("Null arguments to EventGeneratorThread constructor.");
- handlers = eventhandlers;
- session = s;
- client = _client;
- setName(s.sessionDir.getName());
- initWatchers();
- }
-
- private void initWatchers() {
- if (clientfile==null)
- clientfile = session.getClientWatcher();
- if (vamsasfile ==null)
- vamsasfile = session.getDocWatcher();
- if (storeFile == null)
- storeFile = session.getStoreWatcher();
- clientfile.setState();
- vamsasfile.setState();
- storeFile.setState();
- }
- boolean ownsf = false;
- /**
- * scans all watchers and fires changeEvents if necessary
- * @return number of events generated.
- */
- private int checkforEvents() {
- Lock watchlock;
- //TODO : leave slog.info messages for the events that occur.
- int raised=0;
- // could make this general - but for now keep simple
- if ((watchlock=storeFile.getChangedState())!=null) {
- // TODO: define the storeFile semaphore mechanism : file exists - all clients inform their apps, and then the client that wrote the file should delete the file (it should hold the lock to it).
- if (storeFile.exists) {
- PropertyChangeSupport h = (PropertyChangeSupport) handlers.get(Events.DOCUMENT_FINALIZEAPPDATA);
- if (h!=null) {
- log.debug("Triggering DOCUMENT_FINALIZEAPPDATA");
- raised++;
- h.firePropertyChange(client.getSessionUrn(), null, client);
- // expect client to
- vamsasfile.setState();
- }
- }
- }
- if ((watchlock=clientfile.getChangedState())!=null) {
- // see what happened to the clientfile - compare our internal version with the one in the file, or just send the updated list out...?
- //
- /**
- * Generated when a new vamsas client is attached to a session (Handle is
- * passed) Note: the newly created client does not receive the event.
- *
- public static final String CLIENT_CREATION = "org.vamsas.client.events.clientCreateEvent";
- */ // as the test
- /**
- * Generated when a vamsas client leaves a session (Handle is passed to all
- * others).
- public static final String CLIENT_FINALIZATION = "org.vamsas.client.events.clientFinalizationEvent";
- */ // again - as the test.
- raised++;
- }
- if ((watchlock=vamsasfile.getChangedState())!=null) {
-
- /**
- * Generated when a client has finished updating the document. Passes
- * applicationHandle of client so the updating client can recognise its own
- * updates.
- public static final String DOCUMENT_UPDATE = "org.vamsas.client.events.documentUpdateEvent";
- */
- // read apphandle from 'lastUpdate' session file.
- // pass apphandle name to appHandler ?
-
- }
- /**
- * Generated when a new vamsas document is created (perhaps from some existing
- * Vamsas data) so an application may do its own data space initialization.
- * TODO: decide if this is called when an app is connected to a stored
- * session...
- public static final String DOCUMENT_CREATE = "org.vamsas.client.events.documentCreateEvent";
- */
- // check if this session's appInit flag is set - if not - generate event for this app.
- // prolly don't need this at the moment - when an app does getDocument it can to the initing then.
-
-
- /**
- * Generated prior to session Shutdown, after the last participating vamsas
- * client has finalized.
- * TODO: decide on purpose of this ? is this for benefit of multi-session Apps only ?
- public static final String SESSION_SHUTDOWN = "org.vamsas.client.events.SessionShutdownEvent";
- */
-
- /**
- * Generated for all clients when any client calls IClient.storeDocument() to
- * allow them to store any updates before an offline copy of the session is
- * created. Any client that handles this should call the
- * IClient.getDocument(), update and then IClient.updateDocument in the same
- * handler thread.
- * EventName: <Vamsas-session URN>
- * NewValue: org.vamsas.client.IClient for session.
- *
- public static final String DOCUMENT_FINALIZEAPPDATA = "org.vamsas.client.events.DocumentFinalizeAppData";
-*/
- // watch for finalization semaphore (last finalised sessionFile).
-
- /**
- * Generated by Vorba stub after the penultimate client makes a call to
- * closeDocument(). Sequence is as follows : 1. All other vamsas clients have
- * called closeDocument() 2. Final living client monitors closures, and
- * realises that it is last. 3. Final client generates event to prompt
- * associated application to inquire if the user wishes to save the document
- * for future reference.
- * * Any call to closeDocument in a thread other than the registered
- * EventListener will block until the RequestToClose handler has exited.
- *
- */
- // public static final String DOCUMENT_REQUESTTOCLOSE = "org.vamas.client.DocumentRequestToCloseEvent";
-
- return raised;
- }
-
- private void initEvents() {
-
- }
- /**
- * Events raised by IClient and propagated to others in session
- */
-
- /**
- * number of milliseconds between any file state check.
- */
- long POLL_UNIT = 20;
- protected void wait(int u) {
- if (u<=0)
- u=1;
- long l = System.currentTimeMillis()+POLL_UNIT*u;
- while (System.currentTimeMillis()<l)
- ;
- }
-
-
- private boolean block_document_updates=false;
- int STORE_WAIT=5; // how many units before we decide all clients have finalized their appdatas
-
- /**
- * client App requests offline storage of vamsas data.
- * Call blocks whilst other apps do any appData finalizing
- * and then returns (after locking the vamsasDocument in the session)
- * Note - the calling app may also receive events through the EventGeneratorThread for document updates.
- *
- * @return Lock for session.vamArchive
- * @param STORE_WAIT indicates how lock the call will block for when nothing appears to be happening to the session.
- */
- protected Lock want_to_store() {
- log.debug("Setting flag for document_update requests to be ignored");
- block_document_updates=true;
- log.debug("Waiting for other apps to do FinalizeApp handling.");
- try {
- session.addStoreDocumentRequest(client.getClientHandle(), client.getUserHandle());
- } catch (Exception e) {
- log.warn("Whilst writing StoreDocumentRequest for "+client.getClientHandle().getClientUrn()+" "+client.getUserHandle(),
- e);
- log.info("trying to continue.");
- }
- // LATER: refine this semaphore process
- // to make a robust signalling mechanism:
- // app1 requests, app1..n do something (or don't - they may be dead),
- // app1 realises all apps have done their thing, it then continues with synchronized data.
- // this probably needs two files - a request file,
- // and a response file which is acknowledged by the app1 requestor for each app.
- // eventually, no more responses are received for the request, and the app can then only continue with its store.
- int units = 0;
- while (units<STORE_WAIT) {
- wait(1);
- if (storeFile.hasChanged() || vamsasfile.hasChanged())
- units=0;
- else
- units++;
- }
-
- block_document_updates=false;
- log.debug("Cleared flag for ignoring document_update requests");
- // wait around again (until our own watcher has woken up and synchronized).
- while (units<STORE_WAIT) {
- wait(1);
- if (storeFile.hasChanged() || vamsasfile.hasChanged())
- units=0;
- else
- units++;
- }
-
-
- log.debug("finished waiting.");
- return session.vamArchive.getLock();
- }
- /**
- * count handlers for a particular vamsas event
- * @param event string enumeration from org.vamsas.client.Events
- * @return -1 for an invalid event, otherwise the number of handlers
- */
- protected int countHandlersFor(String event) {
- if (handlers.containsKey(event)) {
- PropertyChangeSupport handler = (PropertyChangeSupport) handlers.get(event);
- PropertyChangeListener[] listeners;
- if (handler!=null)
- return ((listeners=handler.getPropertyChangeListeners())==null)
- ? -1 : listeners.length;
- }
- return -1;
- }
- /**
- * probably don't need any of these below.
- */
- /* (non-Javadoc)
- * @see java.lang.Thread#destroy()
- */
- public void destroy() {
- super.destroy();
- }
- /* (non-Javadoc)
- * @see java.lang.Thread#interrupt()
- */
- public void interrupt() {
- // TODO Auto-generated method stub
- super.interrupt();
- }
- /* (non-Javadoc)
- * @see java.lang.Thread#isInterrupted()
- */
- public boolean isInterrupted() {
- // TODO Auto-generated method stub
- return super.isInterrupted();
- }
- /* (non-Javadoc)
- * @see java.lang.Thread#run()
- */
- public void run() {
- // TODO Auto-generated method stub
- super.run();
- }
-
-
-}
+++ /dev/null
-package org.vamsas.client.simpleclient;
-
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.nio.channels.FileChannel;
-import java.nio.channels.ReadableByteChannel;
-/**
- * File based Locking mechanism to get around some bizarre limitations of JarEntry seeking.
- * Abstract locks have a target file, to which access is controlled when a lock is held. Native locks on WindowsXP seem to conflict with Jar seek operations, so a file lock creates an advisory lock.
- * Method:
- * A lock file is created, if it doesn't already exist - the naming convention is TargetFile+suffixSeparator+_LockSuffix.
- * A lock is obtained by locking the lock file with a native lock. The NativeLock is used for this.
- * @author JimP
- *
- */
-public class FileLock extends Lock {
- private File _lock = null;
- protected static String _LockSuffix="lck";
- private NativeLock advisory=null;
- /**
- * ensure that the _lock file exists
- * and create a lock
- */
- private boolean ensureLockFile(boolean block) {
- if (_lock==null)
- return false;
- if (advisory!=null && advisory.isLocked())
- return true;
- try {
- advisory=new NativeLock(_lock, block);
- } catch (Exception e) {
- log.fatal("Failed to create advisory lock file "+_lock,e);
- throw new Error("Failed to create advisory lock file "+_lock);
- }
- return advisory.isLocked();
- }
- /**
- * call to clear up a filelock file after its been made
- *
- */
- private void tidy() {
- if (_lock!=null) {
- if ( advisory!=null)
- advisory.release(true);
- advisory.target.deleteOnExit();
- advisory=null;
- _lock=null;
- }
- }
- /**
- * @param lockfile
- * @param block true means thread blocks until FileLock is obtained.
- */
- public FileLock(File lockfile, boolean block) {
- super(lockfile);
- // try and get a lock.
- try {
- _lock = new File(lockfile.getParentFile(), lockfile.getName()+"."+_LockSuffix);
- if (!ensureLockFile(block)) {
- log.debug("Couldn't get lock on "+_lock);
- tidy();
- return;
- }
- // create target file ready to be written to if necessary.
- if (!lockfile.exists())
- if (!lockfile.createNewFile()) {
- log.warn("Failed to create locked file "+lockfile);
- return;
- }
- //openRaFile();
- } catch (FileNotFoundException e) {
- //
- log.debug("FileLock failed with target="+lockfile+" and lockfile suffix of "+_LockSuffix);
- //log.error("Error! Couldn't create a lockfile at "
- // + lockfile.getAbsolutePath(), e);
- } catch (IOException e) {
- log.error("Error! Problems with IO when creating a lock on "
- + lockfile.getAbsolutePath(),e);
- }
- }
-
- private boolean openRaFile() throws IOException {
- if (target==null)
- return false;
- if (advisory==null || !advisory.isLocked())
- return false;
- if (rafile==null || rafile.getFD()==null || !rafile.getFD().valid()) {
- rafile=new RandomAccessFile(target,"rw");
- } else {
- if (log.isDebugEnabled())
- log.debug("Reusing existing RandomAccessFile on "+target);
- }
- return (rafile.getChannel()!=null) && rafile.getChannel().isOpen();
- }
-
- public boolean isLocked() {
- if (advisory != null) {
- if (advisory.isLocked())
- return true;
- advisory=null;
- if (log.isDebugEnabled())
- log.debug("Lockfile "+_lock+" unexpectedly deleted ?");
- }
- return false;
- }
-
- public void release() {
- release(true);
- }
-
- public void release(boolean closeChannel) {
- if (!isLocked())
- return;
- if (log.isDebugEnabled())
- log.debug("Releasing advisory lock on "+target);
- if (closeChannel) {
- if (rafile!=null)
- try {
- rafile.close();
- } catch (Exception e) {
- log.debug("Unexpected exception whilst closing RandomAccessFile on "+target, e);
- }
- rafile=null;
- }
- tidy();
- }
-
- public FileInputStream getFileInputStream(boolean atStart) throws IOException {
- if (!isLocked()) {
- log.debug("Don't hold lock on "+target+" to get locked FileInputStream.");
- return null;
- }
- openRaFile();
- if (atStart)
- rafile.seek(0);
- return new FileInputStream(rafile.getFD());
- }
-
-
- public FileOutputStream getFileOutputStream(boolean clear) throws IOException {
- if (!isLocked()) {
- log.debug("Don't hold lock on "+target+" to get locked FileOutputStream.");
- return null;
- }
- openRaFile();
- if (clear) {
- rafile.seek(0);
- rafile.setLength(0);
- } else
- rafile.seek(rafile.length());
- return new LockedFileOutputStream(rafile.getFD());
- }
-
-
- public BufferedOutputStream getBufferedOutputStream(boolean clear) throws IOException {
- log.debug("Getting BufferedOutputStream (clear="+clear+")");
- FileOutputStream fos = getFileOutputStream(clear);
- if (fos!=null)
- return new BufferedOutputStream(fos);
- return null;
- }
-
- /* (non-Javadoc)
- * @see org.vamsas.client.simpleclient.Lock#getLength()
- */
- public long length() {
- if (isLocked()) {
- if (!target.exists()) {
- try {
- target.createNewFile();
- } catch (Exception e) {
- log.error("Invalid lock:Failed to create target file "+target);
- tidy();
- return -1;
- }
- return 0;
- }
- return target.length();
- }
- return -1;
- }
- protected void finalize() throws Throwable {
- release(true); // we explicitly lose the lock here.
- super.finalize();
- }
- public RandomAccessFile getRaFile() throws IOException {
- if (isLocked() && openRaFile()) {
- return rafile;
- }
- log.debug("Failed to getRaFile on target "+target);
- return null;
- }
- public FileChannel getRaChannel() throws IOException {
- if (isLocked() && openRaFile()) {
- return rafile.getChannel();
- }
- log.debug("Failed to getRaChannel on target "+target);
- return null;
- }
-}
+++ /dev/null
-/**
- *
- */
-package org.vamsas.client.simpleclient;
-
-import java.io.File;
-
-
-/**
- * Watches a particular file for its creation, deletion, or
- * modification. The watcher is thread safe and different
- * instances watching the state of a particular file carry
- * their own state record for the file.
- */
-public class FileWatcher {
-
- private File subject = null;
-
- private long lastStat[];
- boolean waslocked=false;
- boolean exists = false;
- /**
- * transient lock on subject - can be passed back to calling class
- * to preserve new state of file for immediate reading.
- */
- private Lock subjectLock = null;
- /**
- * clear local locks on subject.
- *
- */
- private void clearLock() {
- if (subjectLock!=null)
- subjectLock.release();
- subjectLock=null;
- }
- /**
- *
- * @return true if subject exists and is locked by another process.
- */
- private boolean checkLock() {
- if (subject!=null && subject.exists()) {
- if (subjectLock!=null) {
- subjectLock.release();
- }
- subjectLock = LockFactory.tryLock(subject);
- if (subjectLock.isLocked()) {
- return false;
- }
- clearLock();
- return true;
- }
- return false;
- }
-
- private long[] getStat(File subject) {
- return new long[] { subject.lastModified(), subject.length() };
- }
- private boolean compStat(long[] stat, long[] newstat) {
- if (stat[0]!=newstat[0] || stat[1]!=newstat[1])
- return false;
- return true;
- }
- /**
- * Detect changes in file state and release of any
- * lock in place during change.
- * @return true if file state has changed. Leaves lock in subjectLock (ready to be passed to caller)
- */
- private boolean check() {
- if (subject != null) {
- if (!subject.exists()) {
- if (exists) {
- if (!waslocked) {
- // !checkLock()) {
-
- exists = false;
- // waslocked=false;
- return true;
- }
- }
- // locked - state change registered after lock is released
- return false;
- } else {
- long[] newStat = getStat(subject); // subject.lastModified();
- if (!checkLock()) {
- // file is free to access, return state change
- if (!exists || !compStat(lastStat, newStat)) {
- waslocked=false;
- exists=true;
- lastStat=newStat;
- return true;
- }
- // no change
- return false;
- } else {
- waslocked=true;
- return false;
- }
- }
- }
- return false;
- }
- /**
- * updates internal record of file state when caller has intentionally
- * modified subject. (ignores locked-state of subject)
- */
- public void setState() {
- if (subject!=null) {
- if (exists = subject.exists()) {
- lastStat = getStat(subject);
- waslocked = false;
- }
- }
- }
-
- /**
- * Make a watcher for a particular file. If the file doesn't exist, the
- * watcher will watch for its creation (and indicate a change of state)
- * For locked files, the removal of a lock constitutes a change of
- * state if the file was modified.
- *
- * @param subject
- */
-
- public FileWatcher(File subject) {
- this.subject = subject;
- setState();
- }
- /**
- * Test for change in file state. Only indicates a change
- * after any lock on a file has been released.
- * @return true if file has been modified.
- */
- public boolean hasChanged() {
- boolean res = check();
- clearLock();
- return res;
- }
- /**
- * passes lock back to caller if hasChanged returned true.
- * @return
- */
- public Lock getChangedState() {
- boolean res = check();
- if (res)
- return subjectLock;
- else {
- clearLock();
- return null;
- }
- }
- /**
- * safely? getting current state of the watched file
- * @return
- */
- public long[] getCurrentState() {
- return getStat(subject);
- }
- /**
- * safely compare an externally recorded state with the current state
- * for significant modifications.
- * @param a
- * @param b
- * @return
- */
- public boolean diffState(long[] a, long[] b) {
- return compStat(a,b);
- }
-}
+++ /dev/null
-/**
- *
- */
-package org.vamsas.client.simpleclient;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.vamsas.client.ClientHandle;
-import org.vamsas.client.SessionHandle;
-import org.vamsas.client.UserHandle;
-import org.vamsas.client.VorbaId;
-import org.vamsas.client.VorbaIdFactory;
-import org.vamsas.client.Vobject;
-import org.vamsas.objects.utils.document.VersionEntries;
-
-import java.util.Hashtable;
-import java.util.zip.CRC32;
-/**
- * Simplest VorbaId constructor
- * @author jimp
- *
- */
-public class IdFactory extends VorbaIdFactory {
- static Log log = LogFactory.getLog(IdFactory.class);
- private SessionHandle session=null;
- private ClientHandle client;
- private UserHandle user;
- private CRC32 unique=new CRC32(); // used to attempt a unique but predictable stream for IDs
- private String idstring;
- int sequence=1; // incrementing value for next new ID
- /**
- *
- */
- public IdFactory() {
- super();
- // TODO Auto-generated constructor stub
- }
-
- /**
- * @param session
- * @param client
- * @param user
- */
- protected IdFactory(SessionHandle session, ClientHandle client, UserHandle user) {
- super();
- this.session = session;
- this.client = client;
- this.user = user;
- unique.reset();
- unique.update(new Object[] { session, client, user}.toString().getBytes());
- // TODO: Ensure format of URNs and use standard composition methods.
- idstring = client.getClientName()+":"+unique.getValue()+".";
- extantids=new Hashtable();
- this.extanthashv=new Hashtable();
- }
- /**
- * values for keys in this hash can be used to reference the org.vamsas.client.Vobject instance for the VorbaId string.
- * @return the hash of all VorbaIds
- */
- protected Hashtable getVorbaIdHash() {
- return extantids;
- }
- /**
- * values for keys in this hash are Vobjhash objects created for each Vobj with a VorbaId
- * after this factory has been used to write a vamsas archive.
- * @return the hash of all VorbaIds and their hash values.
- */
- protected Hashtable getVobjhashVals() {
- return extanthashv;
- }
- /* (non-Javadoc)
- * @see org.vamsas.client.VorbaIdFactory#makeVorbaId()
- */
- public VorbaId makeVorbaId(Vobject vobject) {
- if (session==null)
- throw new Error("makeVorbaId called on improperly initialised IdFactory Vobject!");
- if (!vobject.isRegisterable())
- throw new Error("makeVorbaId called on unregisterable object.");
- if (vobject.isRegistered())
- throw new Error("makeVorbaId called on already registered object.");
- String newidstring;
- do {
- if (sequence>0) {
- sequence++;
- } else {
- idstring+="1/";
- sequence=1;
- }
- newidstring=idstring+Integer.toString(sequence);
- } while (extantids.containsKey(newidstring));
- extantids.put(newidstring, vobject); // hash the Vobject by its new Id
- VorbaId id = newId(newidstring); // VorbaId.hash()==newidstring.hash() so we can still recover vobject
- return id;
- }
-
- /* (non-Javadoc)
- * @see org.vamsas.client.VorbaIdFactory#setSession(org.vamsas.client.SessionHandle)
- */
- protected void setSession(SessionHandle sessionhandle) {
- if (sessionhandle!=null)
- session=sessionhandle;
- else
- log.warn("setSession(null) called.");
- }
-
- /* (non-Javadoc)
- * @see org.vamsas.client.VorbaIdFactory#getSessionHandle()
- */
- public SessionHandle getSessionHandle() {
- return session;
- }
-
- /* (non-Javadoc)
- * @see org.vamsas.client.VorbaIdFactory#setClient(org.vamsas.client.ClientHandle)
- */
- protected void setClient(ClientHandle appHandle) {
- if (appHandle!=null)
- client = appHandle;
- else
- log.warn("setClient(null) called.");
- }
-
- /* (non-Javadoc)
- * @see org.vamsas.client.VorbaIdFactory#getClientHandle()
- */
- public ClientHandle getClientHandle() {
- return client;
- }
-
- /* (non-Javadoc)
- * @see org.vamsas.client.VorbaIdFactory#setUser(org.vamsas.client.UserHandle)
- */
- protected void setUser(UserHandle userHandle) {
- if (userHandle!=null)
- user = userHandle;
- else
- log.warn("setUser(null) called.");
- }
-
- /* (non-Javadoc)
- * @see org.vamsas.client.VorbaIdFactory#getUserHandle()
- */
- public UserHandle getUserHandle() {
- return user;
- }
- /**
- * Convenience method used for default behaviour in testing
- * and any anonymous internal vamsasDocument unmarshalling
- * @param clientname
- * @return
- */
- protected static IdFactory getDummyFactory(String clientname) {
- if (clientname==null)
- clientname="org.vamsas.client.simpleclient.IdFactory";
- return new IdFactory(new SessionHandle("dummy.session"),
- new ClientHandle(clientname,VersionEntries.latestVersion()),
- new UserHandle(clientname, "Arnold User's Inc."));
- }
-}
+++ /dev/null
-/**
- *
- */
-package org.vamsas.client.simpleclient;
-
-import java.io.File;
-
-
-/**
- * base class for generic list storage and retrieval operations from a locked IO file
- * TODO: LATER: generalize for all list storage and retrieval operations
- * (pull-up from ClientsFile object)
- */
-public class ListFile extends SessionFile {
-
- /**
- * @param file
- */
- public ListFile(File file) throws java.io.IOException {
- super(file);
- if (!this.sessionFile.exists())
- this.sessionFile.createNewFile();
- }
-
-}
+++ /dev/null
-package org.vamsas.client.simpleclient;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.RandomAccessFile;
-import java.nio.channels.ByteChannel;
-import java.nio.channels.FileChannel;
-import java.nio.channels.ReadableByteChannel;
-
-import org.apache.commons.logging.LogFactory;
-
-/**
- * transient object representing a file lock
- * This lock should hold for all processes interacting in a session.
- * @author jimp
- */
-
-public abstract class Lock {
- protected org.apache.commons.logging.Log log = LogFactory.getLog(Lock.class);
- File target = null; // The file that is being locked
- protected RandomAccessFile rafile=null;
-
- /**
- * creates a valid Lock (test with <method>isLocked</method>)
- * if a lock could be obtained for <param>lockfile</param>
- * @param lockfile
- */
- protected Lock(java.io.File lockfile) {
- target = lockfile;
- }
- /**
- *
- * @return true if lock is held on the target
- */
- public abstract boolean isLocked();
- /**
- * release lock and close all managed channels to file
- *
- */
- public abstract void release();
- /**
- * optionally close the open random access channel on the file when releasing lock
- * @param closeChannel
- */
- public abstract void release(boolean closeChannel);
-
- /**
- * gets Locked Stream for reading from
- * @param atStart true to start reading at beginning of file.
- * @return null if file not locked
- * @throws IOException
- */
- public abstract FileInputStream getFileInputStream(boolean atStart) throws IOException;
-
- /**
- * gets Locked stream to write to
- * FileInput always starts at the *end* of the file (after any truncation)
- * @param clear true means file will be cleared to zero length
- * @return null if file is not locked
- * @throws IOException
- */
- public abstract FileOutputStream getFileOutputStream(boolean clear) throws IOException;
- /**
- * return buffered output stream to locked file.
- * @param clear - true means file is truncated to 0 length before writing
- * @return
- */
- public abstract BufferedOutputStream getBufferedOutputStream(boolean clear) throws IOException;
-
- protected void finalize() throws Throwable {
- target=null;
- }
- /**
- * return buffered input stream for locked file.
- * @param atStart - true means read from begining of file
- * @return null if file is not locked.
- */
- public BufferedInputStream getBufferedInputStream(boolean atStart) throws IOException {
- FileInputStream fis = getFileInputStream(atStart);
- if (fis!=null)
- return new BufferedInputStream(fis);
- return null;
- }
- /**
- * safe lock target length() function.
- * @return -1 for non-lockable target, otherwise target's file length
- */
- public abstract long length();
- public abstract RandomAccessFile getRaFile() throws IOException;
- public abstract FileChannel getRaChannel() throws IOException;
-}
+++ /dev/null
-package org.vamsas.client.simpleclient;
-
-import java.io.File;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-public class LockFactory {
- protected static Log log = LogFactory.getLog(LockFactory.class);
- public static int locktype=0; // use file lock by default
- public static String[] locktypes = {"file","native"};
- {
- String lockt = System.getProperty("vamsas.locktype");
- if (lockt!=null) {
- int i,j;
- for (i=0, j=locktypes.length; i<j && locktypes[i].equalsIgnoreCase(lockt); i++)
- ;
- if (i>=j) {
- String lt = "'"+locktypes[0]+"'";
- for (i=1; i<j; i++)
- lt += ",'"+locktypes[i]+"'";
- log.warn("System property vamsas.locktype takes one of "+lt);
- log.warn("Defaulting to Locktype of "+locktypes[locktype]);
- }
- } else
- log.debug("Defaulting to Locktype of "+locktypes[locktype]);
- }
- /**
- * lock target (blocks until lock is obtained)
- * @param target
- * @return lock
- */
- public static Lock getLock(java.io.File target) {
- return getLock(target, true);
- }
- public static Lock getLock(java.io.File target, boolean block) {
- if (locktype==0)
- return new FileLock(target, block);
- if (locktype==1)
- return new NativeLock(target, block);
- log.fatal("Implementation Error! No valid Locktype value");
- return null;
- }
- /**
- * try to lock target
- * @param target
- * @return null if lock was not possible
- */
- public static Lock tryLock(File target) {
- return getLock(target, false);
- }
-}
+++ /dev/null
-/**
- *
- */
-package org.vamsas.client.simpleclient;
-
-/**
- * @author jimp
- *
- */
-public class LockTimeoutException extends Exception {
- static final long serialVersionUID=1;
- static final String defaultMessage = "Timeout whilst waiting for lock on VamsasDocument";
- public LockTimeoutException() {
- super(defaultMessage);
- }
- public LockTimeoutException(String arg0, Throwable arg1) {
- super(arg0+" (timeout whilst waiting for lock)", arg1);
- // TODO Auto-generated constructor stub
- }
- public LockTimeoutException(String arg0) {
- super(arg0+" (timeout whilst waiting for lock)");
- // TODO Auto-generated constructor stub
- }
- public LockTimeoutException(Throwable arg0) {
- super(defaultMessage, arg0);
- // TODO Auto-generated constructor stub
- }
-
-}
+++ /dev/null
-/**\r
- * \r
- */\r
-package org.vamsas.client.simpleclient;\r
-\r
-import java.io.File;\r
-import java.io.FileDescriptor;\r
-import java.io.FileNotFoundException;\r
-import java.io.FileOutputStream;\r
-import java.io.IOException;\r
-import java.io.OutputStream;\r
-import java.nio.channels.FileChannel;\r
-\r
-import org.apache.commons.logging.LogFactory;\r
-\r
-/**\r
- * @author Jim\r
- *\r
- */\r
-public class LockedFileOutputStream extends FileOutputStream {\r
- private static org.apache.commons.logging.Log log = LogFactory.getLog(LockedFileOutputStream.class);\r
- //FileOutputStream ostream=null;\r
- boolean closed=true;\r
- private void init() {\r
- FileChannel ch = super.getChannel();\r
- if (ch!=null) {\r
- try { closed = !ch.isOpen();\r
- } catch (Exception e) {\r
- closed=true;\r
- log.debug("Invalid LockedOutputStream marked closed.",e);\r
- }\r
- }\r
- }\r
- /**\r
- * @param file\r
- * @throws FileNotFoundException\r
- */\r
- public LockedFileOutputStream(File file) throws FileNotFoundException {\r
- super(file); // super(file);\r
- init();\r
- }\r
-\r
- /**\r
- * @param file\r
- * @param append\r
- * @throws FileNotFoundException\r
- */\r
- public LockedFileOutputStream(File file, boolean append)\r
- throws FileNotFoundException {\r
- super(file, append);\r
- init();\r
- }\r
-\r
- /**\r
- * @param fdObj\r
- */\r
- public LockedFileOutputStream(FileDescriptor fdObj) {\r
- super(fdObj);\r
- init();\r
- if (fdObj.valid())\r
- closed=false;\r
- }\r
-\r
- /**\r
- * @param name\r
- * @throws FileNotFoundException\r
- */\r
- public LockedFileOutputStream(String name) throws FileNotFoundException {\r
- super(name);\r
- init();\r
- }\r
-\r
- /**\r
- * @param name\r
- * @param append\r
- * @throws FileNotFoundException\r
- */\r
- public LockedFileOutputStream(String name, boolean append)\r
- throws FileNotFoundException {\r
- super(name, append);\r
- init();\r
- }\r
- /**\r
- * closes - actually just flushes the stream instead.\r
- */\r
- public void close() throws IOException {\r
- if (!closed) {\r
- super.flush();\r
- super.getChannel().force(true);\r
- log.debug("Marking Lockedoutputstream closed.");\r
- } else\r
- throw new IOException("Close on already closed FileOutputStream.");\r
- closed=true;\r
- }\r
-\r
-\r
- /**\r
- * @throws IOException\r
- * @see java.io.OutputStream#flush()\r
- */\r
- public void flush() throws IOException {\r
- if (!closed)\r
- super.flush();\r
- else\r
- throw new IOException("flush on closed FileOutputStream");\r
- }\r
-\r
- /**\r
- * @return\r
- * @see java.io.FileOutputStream#getChannel()\r
- */\r
- public FileChannel getChannel() {\r
- if (!closed)\r
- return super.getChannel();\r
- else\r
- return null;\r
- }\r
-\r
-\r
-\r
- /**\r
- * @param b\r
- * @param off\r
- * @param len\r
- * @throws IOException\r
- * @see java.io.FileOutputStream#write(byte[], int, int)\r
- */\r
- public void write(byte[] b, int off, int len) throws IOException {\r
- if (!closed)\r
- super.write(b, off, len);\r
- else\r
- throw new IOException("write on Closed FileOutputStream");\r
- }\r
-\r
- /**\r
- * @param b\r
- * @throws IOException\r
- * @see java.io.FileOutputStream#write(byte[])\r
- */\r
- public void write(byte[] b) throws IOException {\r
- if (!closed)\r
- super.write(b);\r
- else\r
- throw new IOException("write on Closed FileOutputStream");\r
- }\r
-\r
- /**\r
- * @param b\r
- * @throws IOException\r
- * @see java.io.FileOutputStream#write(int)\r
- */\r
- public void write(int b) throws IOException {\r
- if (!closed)\r
- super.write(b);\r
- else\r
- throw new IOException("write on Closed FileOutputStream");\r
- }\r
- \r
-}\r
+++ /dev/null
-package org.vamsas.client.simpleclient;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.io.RandomAccessFile;
-import java.nio.channels.FileChannel;
-import java.nio.channels.FileLock;
-import java.nio.channels.ReadableByteChannel;
-
-/**
- * @author JimP
- *
- */
-public class NativeLock extends Lock {
-
- protected FileLock lock = null;
-
- /**
- * @param lockfile
- * @param block true means thread will block until a lock is obtained.
- */
- public NativeLock(File lockfile, boolean block) {
- super(lockfile);
- // try and get a lock.
- lock = null;
-
- try {
- if (!lockfile.exists())
- if (!lockfile.createNewFile()) {
- log.warn("Failed to create locked file "+lockfile);
- return;
- }
-
- rafile=new RandomAccessFile(lockfile,"rw");
- if (block)
- lock = rafile.getChannel().lock();
- else
- lock = rafile.getChannel().tryLock();
- if (lock==null || !lock.isValid()) {
- // failed to get lock. Close the file channel
- log.debug("failed to get lock for "+lockfile);
- rafile.getChannel().close();
- lock=null;
- }
- } catch (FileNotFoundException e) {
- //
- log.debug("Lock failed - normal behaviour for windows locking.");
- //log.error("Error! Couldn't create a lockfile at "
- // + lockfile.getAbsolutePath(), e);
- } catch (IOException e) {
- log.error("Error! Problems with IO when creating a lock on "
- + lockfile.getAbsolutePath(),e);
- }
- }
-
- public boolean isLocked() {
- if (lock != null && lock.isValid()) {
- return true;
- }
- return false;
- }
-
- public void release() {
- release(true);
- }
-
- public void release(boolean closeChannel) {
- try {
- // channel.close should be called before release() for rigourous locking.
- if (rafile!=null && rafile.getFD().valid() && rafile.getChannel()!=null && lock.isValid()) {
- if (closeChannel && rafile.getChannel().isOpen()) {
- rafile.close();
- rafile=null;
- }
- if (lock!=null && lock.isValid())
- lock.release();
-
- }
- } catch (IOException e) {
- log.warn("Whilst releasing lock",e);
- }
- lock=null;
- }
-
- /**
- * gets Locked Stream for reading from
- * @param atStart true to start reading at beginning of file.
- * @return null if file not locked
- * @throws IOException
- */
- public FileInputStream getFileInputStream(boolean atStart) throws IOException {
- if (!isLocked())
- return null;
- if (atStart)
- rafile.seek(0);
- return new FileInputStream(rafile.getFD());
- }
-
- /**
- * gets Locked stream to write to
- * FileInput always starts at the *end* of the file (after any truncation)
- * @param clear true means file will be cleared to zero length
- * @return null if file is not locked
- * @throws IOException
- */
- public FileOutputStream getFileOutputStream(boolean clear) throws IOException {
- if (!isLocked())
- return null;
- if (clear) {
- rafile.seek(0);
- rafile.setLength(0);
- } else
- rafile.seek(rafile.length());
- return new LockedFileOutputStream(rafile.getFD());
- }
-
- /**
- * return buffered output stream to locked file.
- * @param clear - true means file is truncated to 0 length before writing
- * @return
- */
- public BufferedOutputStream getBufferedOutputStream(boolean clear) throws IOException {
- OutputStream fos = getFileOutputStream(clear);
- if (fos!=null)
- return new BufferedOutputStream(fos);
- return null;
- }
- /**
- * @see org.vamsas.client.simpleclient.Lock#finalize()
- */
- protected void finalize() throws Throwable {
- release(true); // we explicitly lose the lock here.
- // log.debug("lock closing through garbage collection ?");
- super.finalize();
- }
-
- /* (non-Javadoc)
- * @see org.vamsas.client.simpleclient.Lock#getLength()
- */
- public long length() {
- if (isLocked()){
- try {
- return rafile.length();
- } catch (Exception e) {
- log.debug("getLength exception:",e);
- }
- }
- return -1;
- }
-
- public RandomAccessFile getRaFile() throws IOException {
- if (isLocked())
- return rafile;
- else
- log.debug("Failed to getRaFile on "+target);
- return null;
- }
-
- public FileChannel getRaChannel() throws IOException {
- if (isLocked())
- return rafile.getChannel();
- else
- log.debug("Failed to getRaChannel on "+target);
- return null;
- }
-
-}
+++ /dev/null
-package org.vamsas.client.simpleclient;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.nio.channels.ReadableByteChannel;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * Basic methods for classes handling locked IO on files
- * monitored by all (simpleclient) clients in a vamsas session.
- * @author jimp
- *TODO: support non nio file locking capable systems
- */
-public class SessionFile {
- private static Log log = LogFactory.getLog(SessionFile.class);
- protected File sessionFile;
- protected Lock fileLock = null;
-
- protected SessionFile(File file) {
- super();
- sessionFile = file;
- }
-
- protected boolean lockFile(Lock extantlock) {
- if (fileLock!=null && !fileLock.isLocked()) {
- fileLock.release();// tidy up invalid lock
- fileLock=null;
- }
- if (extantlock!=null && extantlock.isLocked())
- fileLock=extantlock; // THIS IS BROKEN - lockFile then nulls the lock.
- return lockFile();
- }
- private boolean ensureSessionFile() {
- if (sessionFile != null) {
- if (!sessionFile.exists()) {
- // create new file
- try {
- if (!sessionFile.createNewFile()) {
- log.error("Failed to create file prior to locking: "+sessionFile);
- return false;
- }
- } catch (IOException e) {
- log.error("Exception when trying to create file "+sessionFile, e);
- return false;
- }
- }
- return true;
- }
- log.error("ensureSessionFile called for non-initialised SessionFile!");
- return false;
- }
- /**
- * Get a lock for the SessionFile
- *
- * @return true if lock was made
- */
- protected boolean lockFile() {
- if (fileLock != null) {
- if (fileLock.isLocked()) {
- if (!ensureSessionFile())
- return false;
- return true;
- } else {
- // lock failed for some reason.
- fileLock.release();
- log.info("Unexpected session file lock failure. Trying to get it again.");
- fileLock=null;
- }
- }
- if (!ensureSessionFile())
- return false;
- // TODO: see if we need to loop-wait for locks or they just block until
- // lock is made...
- long tries=5000;
- do {
- tries--;
- if (fileLock==null || !fileLock.isLocked()) {
- //try { Thread.sleep(1); } catch (Exception e) {};
- fileLock = LockFactory.getLock(sessionFile,true); // TODO: wait around if we can't get the lock.
- }
- } while (tries>0 && !fileLock.isLocked());
- if (!fileLock.isLocked())
- log.error("Failed to get lock for "+sessionFile);
- // fileLock = new Lock(sessionFile);
- return fileLock.isLocked();
- }
-
- /**
- * Explicitly release the SessionFile's lock.
- *
- * @return true if lock was released.
- */
- protected void unlockFile() {
- if (fileLock != null) {
- fileLock.release();
- fileLock = null;
- }
- }
-
- /**
- * Makes a backup of the sessionFile.
- * @return Backed up SessionFile or null if failed to make backup.
- */
- protected File backupSessionFile() {
- return backupSessionFile(null, sessionFile.getName(),".old", sessionFile.getParentFile());
- }
-
- protected File backupSessionFile(Lock extantLock, String backupPrefix, String backupSuffix, File backupDir) {
- File tempfile=null;
- if (lockFile(extantLock)) {
- try {
- tempfile = File.createTempFile(backupPrefix, backupSuffix, backupDir);
- if (fileLock.length()>0) {
- FileOutputStream tos = new FileOutputStream(tempfile);
- ReadableByteChannel channel;
- tos.getChannel().transferFrom(channel=fileLock.getRaChannel(), 0,
- fileLock.length());
- tos.close();
- if (!channel.isOpen())
- throw new Error(tos.getChannel().getClass()+".transferFrom closes source channel!");
- if (!lockFile(extantLock))
- throw new Error("Lost lock for "+sessionFile.getName()+" after backup.");
-
- }
- } catch (FileNotFoundException e1) {
- log.warn("Can't create temp file for "+sessionFile.getName(),e1);
- tempfile=null;
- } catch (IOException e1) {
- log.warn("Error when copying content to temp file for "+sessionFile.getName(),e1);
- tempfile=null;
- }
- }
- return tempfile;
- }
- /**
- * Replaces data in sessionFile with data from file handled by another sessionFile
- * passes up any exceptions.
- * @param newData source for new data
- */
- protected void updateFrom(Lock extantLock, SessionFile newData) throws IOException {
- log.debug("Updating "+sessionFile.getAbsolutePath()+" from "+newData.sessionFile.getAbsolutePath());
- if (newData==null)
- throw new IOException("Null newData object.");
- if (newData.sessionFile==null)
- throw new IOException("Null SessionFile in newData.");
-
- if (!lockFile(extantLock))
- throw new IOException("Failed to get write lock for "+sessionFile);
- if (!newData.lockFile())
- throw new IOException("Failed to get lock for updateFrom "+newData.sessionFile);
- RandomAccessFile nrafile = newData.fileLock.getRaFile();
- nrafile.seek(0);
- RandomAccessFile trafile = fileLock.getRaFile();
- /*long tries=5000;
- while (trafile==null && --tries>0) {
- log.debug("Lost lock on "+sessionFile+"! Re-trying for a transfer.");
- lockFile();
- trafile = fileLock.getRaFile();
- }*/
- trafile.seek(0);
- trafile.getChannel().transferFrom(nrafile.getChannel(), 0,
- nrafile.length());
- }
- /**
- * remove all trace of the sessionFile file
- *
- */
- protected void eraseExistence() {
- unlockFile();
- if (sessionFile!=null) {
- sessionFile.delete();
- sessionFile = null;
- }
- }
- /* (non-Javadoc)
- * @see org.vamsas.client.simpleclient.Lock#getBufferedInputStream(boolean)
- */
- public BufferedInputStream getBufferedInputStream(boolean atStart) throws IOException {
- lockFile();
- return fileLock.getBufferedInputStream(atStart);
- }
-
- /* (non-Javadoc)
- * @see org.vamsas.client.simpleclient.Lock#getBufferedOutputStream(boolean)
- */
- public BufferedOutputStream getBufferedOutputStream(boolean clear) throws IOException {
- lockFile();
- return fileLock.getBufferedOutputStream(clear);
- }
-
- /* (non-Javadoc)
- * @see org.vamsas.client.simpleclient.Lock#getFileInputStream(boolean)
- */
- public FileInputStream getFileInputStream(boolean atStart) throws IOException {
- lockFile();
- return fileLock.getFileInputStream(atStart);
- }
-
- /* (non-Javadoc)
- * @see org.vamsas.client.simpleclient.Lock#getFileOutputStream(boolean)
- */
- public FileOutputStream getFileOutputStream(boolean clear) throws IOException {
- lockFile();
- return fileLock.getFileOutputStream(clear);
- }
-
-}
+++ /dev/null
-package org.vamsas.client.simpleclient;
-
-import java.io.File;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-/**
- * methods for setting and checking
- * binary flags in a vamsas session directory.
- * all methods apart from the constructor will
- * throw a fatal error if the flagFile is not
- * a valid java.io.File object.
- * LATER: extract SessionFlag interface for generalizing the vamsas session code
- * @author jimp
- *
- */
-public class SessionFlagFile {
- private static Log log = LogFactory.getLog(SessionFlagFile.class);
- protected File flagFile=null;
- private void checkFlagFile() {
- if (flagFile==null) {
- log.fatal("Implementation error - uninitialized SessionFlagFile",
- new Error("Implementation error - uninitialized SessionFlagFile"));
- }
- }
- /**
- * will log a warning if exceptions occur during flag creation.
- * @return true if flag was set successfully
- */
- public boolean setFlag() {
- checkFlagFile();
- try {
- if (flagFile.createNewFile()) {
- log.debug("Set session flag "+flagFile);
- } else {
- log.debug("Session flag already set "+flagFile);
- }
- return true;
- }
- catch (Exception e) {
- log.warn("Couldn't set session flag "+flagFile, e);
- }
- return false;
- }
- /**
- *
- * @return true if flag was cleared successfully
- */
- public boolean clearFlag() {
- checkFlagFile();
- if (flagFile.exists()) {
- log.debug("clearing session flag "+flagFile);
- if (!flagFile.delete()) {
- log.warn("failed to clear session flag "+flagFile);
- return false;
- }
- } else {
- log.debug("clearFlag called for already cleared flag "+flagFile);
- }
- return true;
- }
- /**
- *
- * @return state of session flag
- */
- public boolean checkFlag() {
- checkFlagFile();
- if (flagFile.exists()) {
- if (log.isDebugEnabled())
- log.debug("Flag '"+flagFile+"' is set.");
- return true;
- }
- if (log.isDebugEnabled())
- log.debug("Flag '"+flagFile+"' is not set.");
- return false;
- }
- /**
- * @param flagFile
- */
- public SessionFlagFile(File flagFile) {
- super();
- this.flagFile = flagFile;
- };
-}
+++ /dev/null
-package org.vamsas.client.simpleclient;
-
-import java.io.File;
-import java.net.MalformedURLException;
-
-/**
- * SessionUrn for simpleclient sessions:
- * simpleclient://{Absolute path to session directory}
- * @author jimp
- *
- */
-public class SessionUrn extends org.vamsas.client.SessionUrn {
- /**
- * a simple client session urn prefix
- */
- public static final String SIMPLECLIENT="simpleclient";
- public static String VAMSASDOCUMENT="vdoc";
- static {
- TYPES.put(SIMPLECLIENT, SessionUrn.class);
- TYPES.put(SessionUrn.VAMSASDOCUMENT, SessionUrn.class);
- }
-
- public SessionUrn(File sessionLocation) throws MalformedURLException {
- // TODO: LATER: implement switch to have vamsas document or simpleclient sessions for same constructor
- super(SIMPLECLIENT, sessionLocation.getAbsoluteFile().toURL());
- //else
- // super(VAMSASDOCUMENT, sessionLocation);
- }
- public SessionUrn(VamsasSession session) throws MalformedURLException {
- super(SIMPLECLIENT, session.sessionDir.getAbsoluteFile().toURL());
- }
- /**
- * TODO: LATER: think about this again.
- * @return File(urn.getPath())
- */
- public File asFile() {
- return new File(urn.getPath());
- }
- // TODO: add abstract 'handler' methods for resolving the URN to a particular class
-}
+++ /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);
-
- }
- }
-
- }
-}
+++ /dev/null
-/*
- * Created on 15-Sep-2005
- *
- * TODO To change the template for this generated file go to
- * Window - Preferences - Java - Code Style - Code Templates
- */
-package org.vamsas.client.simpleclient;
-
-import java.beans.EventHandler;
-import java.beans.PropertyChangeEvent;
-import java.beans.PropertyChangeListener;
-import java.beans.PropertyChangeSupport;
-import java.io.BufferedReader;
-import java.io.File;
-import java.io.IOException;
-import java.net.MalformedURLException;
-import java.util.Hashtable;
-import java.util.Vector;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.vamsas.client.ClientHandle;
-import org.vamsas.client.Events;
-import org.vamsas.client.IClient;
-import org.vamsas.client.IClientDocument;
-import org.vamsas.client.IObjectUpdate;
-import org.vamsas.client.InvalidSessionUrnException;
-import org.vamsas.client.SessionHandle;
-import org.vamsas.client.UserHandle;
-import org.vamsas.objects.core.ApplicationData;
-import org.vamsas.objects.core.Entry;
-import org.vamsas.objects.core.LockFile;
-import org.vamsas.objects.core.VamsasDocument;
-import org.vamsas.objects.utils.AppDataReference;
-import org.vamsas.objects.utils.ProvenanceStuff;
-import org.vamsas.objects.utils.document.VersionEntries;
-
-/**
- * @author jimp
- */
-public class SimpleClient implements IClient {
-
- private static Log log = LogFactory.getLog(SimpleClient.class);
-
- protected UserHandle user = null;
-
- protected SessionUrn session = null;
- protected VamsasSession _session;
- protected ClientHandle client = null;
- protected EventGeneratorThread evgen = null;
- protected ClientDocument cdocument = null;
- /**
- * object hash table that persists in each client holding vorbaIds and hash values after a document write
- */
- protected Hashtable extantobjects=null;
- /**
- * construct a transient IdFactory instance - this should last only as long as the
- * SimpleClient object holds the lock on the vamsas document being created/manipulated.
- * @return
- */
- private IdFactory makeVorbaIdFactory() {
- return new IdFactory(getSessionHandle(), client, user);
- }
-
- /**
- * construct SimpleClient for user, client and VamsasSession directory
- * use the SimpleClientFactory rather than this constructor directly.
- * @param user
- * @param client
- * @param sess
- */
- protected SimpleClient(UserHandle user, ClientHandle client, VamsasSession sess) throws InvalidSessionUrnException {
- // TODO: validate user/client/session
- _session = sess;
- this.user = user;
- this.client = client;
- try {
- session = new SessionUrn(_session);
- } catch (MalformedURLException e) {
- log.error("Couldn't form a valid SessionUrn object!",e);
- throw new InvalidSessionUrnException(_session.toString());
- }
- }
- /**
- * construct new session by importing objects from an existing vamsas document
- * @param user
- * @param client
- * @param sess
- * @param importingArchive
- * @throws Exception IOExceptions for Session IO problems, and general Exception if importing document is invalid.
- */
- protected SimpleClient(UserHandle user, ClientHandle client, VamsasSession sess, File importingArchive) throws Exception {
- this(user, client, sess);
- VamsasArchive sessdoc = _session.getVamsasDocument();
- try {
- VamsasArchiveReader odoc = new VamsasArchiveReader(importingArchive);
- SimpleDocument sdoc = new SimpleDocument(makeVorbaIdFactory());
- VamsasDocument doc = sdoc.getVamsasDocument(odoc);
- sessdoc.putVamsasDocument(doc, sdoc.vorba);
- sessdoc.closeArchive();
- } catch (Exception e) {
- sessdoc.cancelArchive();
- // write a dummy archive
- _session.slog.info("Exception when importing document data from "+importingArchive);
- throw new Exception("Failed to import data from "+importingArchive, e);
- }
- }
-
- /*
- * (non-Javadoc)
- * LATER: check that build substitution variables are correct
- * @see org.vamsas.client.IClient#getAbout()
- */
- public String getAbout() {
- return new String("VORBA SimpleClient version $version$ build $build$");
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.vamsas.client.IClient#getSessionUrn()
- */
- public String getSessionUrn() {
- return session.getSessionUrn();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.vamsas.client.IClient#getSessionHandle()
- */
- public SessionHandle getSessionHandle() {
- // TODO: eliminate SessionHandle ? need to refactor interfaces.
- SessionHandle sh = new SessionHandle(session.getSessionUrn());
- return sh;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.vamsas.client.IClient#getClientHandle()
- */
- public ClientHandle getClientHandle() {
- return client;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.vamsas.client.IClient#getUserHandle()
- */
- public UserHandle getUserHandle() {
- return user;
- }
- /**
- *
- * @return user field for a provenance entry
- */
- protected String getProvenanceUser() {
- return new String(user.getFullName());
- }
- /**
- * construct a provenance entry for this client with the specified action string.
- * @param action
- * @return properly completed provenance entry
- */
- protected Entry getProvenanceEntry(String action) {
- Entry prov = ProvenanceStuff.newProvenanceEntry(client.getClientUrn(), getProvenanceUser(), action);
- return prov;
- }
- private Hashtable handlers = initHandlers();
-
- private Vector listeners = new Vector();
-
- /**
- * make all the PropertyChangeSupport objects for the
- * events described in org.vamsas.client.Event
- * @return
- */
- private static Hashtable initHandlers() {
- Hashtable events = new Hashtable();
- java.util.Iterator evt = Events.EventList.iterator();
- while (evt.hasNext()) {
- Object ths = evt.next();
- events.put(ths, (Object) new PropertyChangeSupport(ths));
- }
- return events;
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.vamsas.client.IClient#addDocumentUpdateHandler(java.util.EventListener)
- */
- public void addDocumentUpdateHandler(PropertyChangeListener evt) {
- if (handlers.containsKey(Events.DOCUMENT_UPDATE)) {
- Object handler;
- ((PropertyChangeSupport) (handler = handlers.get(Events.DOCUMENT_UPDATE)))
- .addPropertyChangeListener(evt);
- listeners.add(handler);
- listeners.add((Object) evt);
- }
- }
- boolean finalized=false;
- /*
- * (non-Javadoc)
- *
- * @see org.vamsas.client.IClient#finalizeClient()
- */
- public void finalizeClient() {
- // TODO: determine if this is last client in session
- // TODO: raise events like : ((lst_client && document.request.to.close), (client_finalization), (
-
- // if (handlers.containsKey(Events.))
- // if (handlers.containsKey(Events.CLIENT_FINALIZATION))
- // deregister listeners.
- // mark this instance as finalized
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.vamsas.client.IClient#getClientDocument()
- */
- public IClientDocument getClientDocument() throws IOException {
- if (cdocument!=null) {
- // cdocument is non-nill if the ClientDocument.finalise() method hasn't been called.
- return cdocument;
- }
- VamsasArchive va = null;
- try {
- // LATER: bail out if it takes too long to get the lock ?
- va = _session.getVamsasDocument();
- }
- catch (IOException e) {
- throw new IOException("Failed to get lock on session document");
- }
- VamsasDocument doc=null;
- IdFactory vorba = null;
- // TODO: reduce size of vorba ids generated from these parameters to IdFactory (mainly sessionHandle rationalization ?)
- try {
- va.setVorba(vorba=makeVorbaIdFactory());
- // if session currently holds data - read it in - or get a dummy
- _session.slog.debug("Accessing document");
- doc =
- va.getVamsasDocument(getProvenanceUser(),
- "created new session document.", null);
- if (doc!=null)
- _session.slog.debug("Successfully retrieved document.");
- else
- log.error("Unexpectedly retrieved null document!");
- }
- catch (Exception e) {
- log.error("Failed to get session document for session directory '"+_session.sessionDir+"'", e);
- throw new IOException("Failed to get session document for session directory '"+_session.sessionDir+"'");
- }
- // Construct the IClientDocument instance
-
- ClientDocument cdoc = new ClientDocument(doc, va, vorba, this);
- return cdoc;
- }
-
- /*
- * (non-Javadoc)
- * @throws Errors for invalid newdoc parameter
- * @see org.vamsas.client.IClient#updateDocument(org.vamsas.client.IClientDocument)
- */
- public void updateDocument(IClientDocument newdoc) {
- if (!(newdoc instanceof ClientDocument)) {
- throw new Error("Invalid IClientDocument instance for SimpleClient.");
- }
- if (cdocument==null)
- throw new Error("Client Error - updateDocument() called before getClientDocument().");
- if (newdoc!=cdocument)
- throw new Error("Client Error - SimpleClient.updateDocument() can only take the IClientDocument instance returned from SimpleClient.getClientDocument()");
- if (!cdocument.isModified()) {
- if (log.isDebugEnabled())
- log.debug("updateDocument for "+session.getSessionUrn()+" with unmodified IClientDocument.");
- } else {
- try {
- if (!cdocument.updateSessionDocument()) {
- log.warn("Session document did not update properly for session directory "+_session.sessionDir);
- // cdocument.archive.cancelArchive(); // LATER: could be done - would need to prevent updateSessionDocument closing the archive.
- _session.slog.warn("Session Document updated but may not be valid (false return from org.vamsas.simpleclient.ClientDocument.updateSessionDocument()");
- }
- }
- catch (IOException e) {
- log.warn("IO Problems when updating document!",e);
- _session.slog.error("IO problems when attempting to update document.");
- }
- }
- // garbage collect the ClientDocument instance.
- try {
- cdocument.finalize();
-
- } catch (Throwable e) {
- log.error("Exception when trying to garbage collect ClientDocument for "+session.getSessionUrn(), e);
- }
- cdocument = null; // this is probably done by finalize
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.vamsas.client.IClient#storeDocument(java.io.File)
- */
- public void storeDocument(File location) {
-
- // write storeDocument file to inform other clients that they should raise
- Lock vamlock = evgen.want_to_store();
- // Events.DOCUMENT_FINALIZEAPPDATA
- try {
- _session.writeVamsasDocument(location, vamlock);
- _session.clearUnsavedFlag();
- } catch (Exception e) {
- log.warn("Exception whilst trying to store document in "+location,e);
- }
-
- vamlock.release();
- }
-
- /*
- * (non-Javadoc)
- *
- * @see org.vamsas.client.IClient#addVorbaEventHandler(java.lang.String,
- * java.beans.PropertyChangeListener)
- */
- public void addVorbaEventHandler(String EventChain, PropertyChangeListener evt) {
- if (handlers.containsKey(EventChain)) {
- Object handler;
- ((PropertyChangeSupport) (handler = handlers.get(EventChain)))
- .addPropertyChangeListener(evt);
- listeners.add(handler);
- listeners.add((Object) evt);
- }
- }
-
- /* (non-Javadoc)
- * @see org.vamsas.client.IClient#pollUpdate()
- */
- public void pollUpdate() {
-
- if (evgen==null) {
- log.warn("pollUpdate called on incomplete SimpleClient object.");
- return;
- }
-
- if (!evgen.isAlive()) {
- log.warn("pollUpdate called before joinSession() - trying to do this.");
- try {
- joinSession();
- } catch (Exception e) {
- log.error("Unexpected exception on default call to joinSession",e);
- }
- }
-
- //TODO ensure event generator robustly handles these interrupts.
- log.debug("interrrupting event generator.");
- evgen.interrupt();
- log.debug("interrrupted event generator.");
- }
-
- /* (non-Javadoc)
- * @see org.vamsas.client.IClient#joinSession()
- */
- public void joinSession() throws Exception {
- // start the EventGenerator thread.
- if (evgen==null) {
- log.warn("joinSession called on incomplete SimpleClient object.");
- return;
- }
- if (evgen.isAlive())
- throw new Error("Join session called twice for the same SimpleClient (IClient instance).");
- evgen.start();
- if (evgen.isAlive())
- log.debug("Started EventGenerator thread.");
- else {
- log.warn("Failed to start EventGenerator thread.");
- throw new Exception("Failed to start event generator thread - client cannot be instantiated.");
- }
- if (evgen.countHandlersFor(Events.DOCUMENT_CREATE)>0) {
- //TODO: is this application connecting to a newly created session document ?
- //evgen.raise(Events.DOCUMENT_CREATE);
- }
- }
-
-
-
- /* (non-Javadoc)
- * @see org.vamsas.client.IClient#importDocument(java.io.File)
- */
- public void importDocument(File location) {
- // TODO LATER: implement SimpleClient.importDocument()
- log.error("importDocument is not yet implemented for a SimpleClient Session.");
- }
-
- public IObjectUpdate getUpdateHandler(Class rootObject) {
- // TODO Auto-generated method stub
- return null;
- }
-
- public IObjectUpdate[] getUpdateHandlers() {
- // TODO Auto-generated method stub
- return null;
- }
-
- public void removeUpdateHandler(Class rootObject) {
- // TODO Auto-generated method stub
-
- }
-
- public void setUpdateHandler(IObjectUpdate handler) {
- // TODO Auto-generated method stub
-
- }
-}
+++ /dev/null
-/**
- *
- */
-package org.vamsas.client.simpleclient;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.DataInput;
-import java.io.DataInputStream;
-import java.io.DataOutput;
-import java.io.DataOutputStream;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.util.Vector;
-import java.util.jar.JarEntry;
-import java.util.jar.JarInputStream;
-import java.util.jar.JarOutputStream;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.vamsas.client.IClientAppdata;
-import org.vamsas.objects.core.AppData;
-import org.vamsas.objects.core.ApplicationData;
-import org.vamsas.objects.core.User;
-import org.vamsas.objects.utils.AppDataReference;
-
-/**
- * @author jimp
- * Access interface to data chunks read from a VamsasArchiveReader stream
- * (or byte buffer input stream) or written to a VamsasArchive stream.
- * // TODO: get VamsasArchiveReader from sclient
- */
-public class SimpleClientAppdata implements IClientAppdata {
- private static Log log = LogFactory.getLog(SimpleClientAppdata.class);
- /**
- * has the session's document been accessed to get the AppData entrys?
- */
- protected boolean accessedDocument = false;
- /**
- * has the user datablock been modified ?
- * temporary file containing new user specific application data chunk
- */
- SessionFile newUserData=null;
- JarOutputStream newUserDataStream = null;
- /**
- * has the apps global datablock been modified ?
- * temporary file containing new global application data chunk
- */
- SessionFile newAppData=null;
- JarOutputStream newAppDataStream=null;
- /**
- * set by extractAppData
- */
- protected ApplicationData appsGlobal = null;
- /**
- * set by extractAppData
- */
- protected User usersData = null;
-
- ClientDocument clientdoc;
- /**
- * state flags
- * - accessed ClientAppdata
- * - accessed UserAppdata
- * => inputStream from embedded xml or jar entry of backup has been created
- * - set ClientAppdata
- * - set UserAppdata
- * => an output stream has been created and written to - or a data chunk has been written.
- * - need flag for switching between embedded and jar entry mode ? - always write a jar entry for a stream.
- * - need code for rewind and overwriting if the set*Appdata methods are called more than once.
- * - need flags for streams to except a call to set*Appdata when an output stream exists and is open.
- * - need
- * @param clientdoc The ClientDocument instance that this IClientAppData is accessing
- */
- protected SimpleClientAppdata(ClientDocument clientdoc) {
- if (clientdoc==null) {
- log.fatal("Implementation error - Null ClientDocument for SimpleClientAppdata construction.");
- throw new Error("Implementation error - Null ClientDocument for SimpleClientAppdata construction.");
- }
- this.clientdoc = clientdoc;
- }
- /**
- * gets appropriate app data for the application, if it exists in this dataset
- * Called by every accessor to ensure data has been retrieved from document.
- */
- private void extractAppData(org.vamsas.objects.core.VamsasDocument doc) {
- if (doc==null) {
- log.debug("extractAppData called for null document object");
- return;
- }
- if (accessedDocument) {
- return;
- }
- Vector apldataset = AppDataReference.getUserandApplicationsData(
- doc, clientdoc.sclient.getUserHandle(), clientdoc.sclient.getClientHandle());
- accessedDocument = true;
- if (apldataset!=null) {
- if (apldataset.size()>0) {
- AppData clientdat = (AppData) apldataset.get(0);
- if (clientdat instanceof ApplicationData) {
- appsGlobal = (ApplicationData) clientdat;
- if (apldataset.size()>1) {
- clientdat = (AppData) apldataset.get(1);
- if (clientdat instanceof User) {
- usersData = (User) clientdat;
- }
- if (apldataset.size()>2)
- log.info("Ignoring additional ("+(apldataset.size()-2)+") AppDatas returned by document appdata query.");
- }
- } else {
- log.warn("Unexpected entry in AppDataReference query: id="+clientdat.getVorbaId()+" type="+clientdat.getClass().getName());
- }
- apldataset.removeAllElements(); // destroy references.
- }
- }
- }
- /**
- * LATER: generalize this for different low-level session implementations (it may not always be a Jar)
- * @param appdata
- * @param docreader
- * @return
- */
- private JarInputStream getAppDataStream(AppData appdata, VamsasArchiveReader docreader) {
- String entryRef = appdata.getDataReference();
- if (entryRef!=null) {
- log.debug("Resolving appData reference +"+entryRef);
- InputStream entry = docreader.getAppdataStream(entryRef);
- if (entry!=null) {
- if (entry instanceof JarInputStream) {
- return (JarInputStream) entry;
- }
- log.warn("Implementation problem - docreader didn't return a JarInputStream entry.");
- }
- } else {
- log.debug("GetAppDataStream called for an AppData without a data reference.");
- }
- return null;
- }
- /**
- * yuk - size of buffer used for slurping appData JarEntry into a byte array.
- */
- private final int _TRANSFER_BUFFER=4096*4;
-
- /**
- * Resolve AppData object to a byte array.
- * @param appdata
- * @param archiveReader
- * @return null or the application data as a byte array
- */
- private byte[] getAppDataAsByteArray(AppData appdata, VamsasArchiveReader docreader) {
- if (appdata.getData()==null) {
- if (docreader==null) {
- log.warn("Silently failing getAppDataAsByteArray with null docreader.",new Exception());
- return null;
- }
- // resolve and load data
- JarInputStream entry = getAppDataStream(appdata, docreader);
- ByteArrayOutputStream bytes = new ByteArrayOutputStream();
- try {
- byte buff[] = new byte[_TRANSFER_BUFFER];
- int olen=0;
- while (entry.available()>0) {
- int len = entry.read(buff, olen, _TRANSFER_BUFFER);
- bytes.write(buff, 0, len);
- olen+=len;
- }
- buff=null;
- } catch (Exception e) {
- log.warn("Unexpected exception - probable truncation when accessing VamsasDocument entry "+appdata.getDataReference(), e);
- }
- if (bytes.size()>0) {
- // LATER: deal with probable OutOfMemoryErrors here
- log.debug("Got "+bytes.size()+" bytes from AppDataReference "+appdata.getDataReference());
- byte data[] = bytes.toByteArray();
- bytes = null;
- return data;
- }
- return null;
- } else {
- log.debug("Returning inline AppData block for "+appdata.getVorbaId());
- return appdata.getData();
- }
- }
- /**
- * internal method for getting a DataInputStream from an AppData object.
- * @param appdata
- * @param docreader
- * @return data in object or null if no data is accessible
- */
- private DataInput getAppDataAsDataInputStream(AppData appdata, VamsasArchiveReader docreader) {
- if (appdata!=null && docreader!=null) {
- String entryRef = appdata.getDataReference();
- if (entryRef!=null) {
- log.debug("Resolving AppData reference for "+entryRef);
- InputStream jstrm = docreader.getAppdataStream(entryRef);
- if (jstrm!=null)
- return new AppDataInputStream(jstrm);
- else {
- log.debug("Returning null input stream for unresolved reference ("+entryRef+") id="+appdata.getVorbaId());
- return null;
- }
- } else {
- // return a byteArray input stream
- byte[] data=appdata.getData();
- if (data.length>0) {
- ByteArrayInputStream stream = new ByteArrayInputStream(data);
- return new DataInputStream(stream);
- } else {
- log.debug("Returning null input stream for empty Appdata data block in id="+appdata.getVorbaId());
- return null;
- }
- }
- } else {
- log.debug("Returning null DataInputStream for appdata entry:"+appdata.getVorbaId());
- }
- return null;
- }
-
- /**
- * internal method for getting ByteArray from AppData object
- * @param clientOrUser - true for returning userData, otherwise return Client AppData.
- * @return null or byte array
- */
- private byte[] _getappdataByteArray(boolean clientOrUser) {
- if (clientdoc==null)
- throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
- byte[] data=null;
- String appdName;
- if (!clientOrUser) {
- appdName = "Client's Appdata";
- } else {
- appdName = "User's Appdata";
- }
- log.debug("getting "+appdName+" as a byte array");
- extractAppData(clientdoc.getVamsasDocument());
- AppData object;
- if (!clientOrUser) {
- object = appsGlobal;
- } else {
- object = usersData;
- }
- if (object!=null) {
- log.debug("Trying to resolve "+appdName+" object to byte array.");
- data = getAppDataAsByteArray(object, clientdoc.getVamsasArchiveReader());
- }
- if (data == null)
- log.debug("Returning null for "+appdName+"ClientAppdata byte[] array");
- return data;
-
- }
-
- /**
- * common method for Client and User AppData->InputStream accessor
- * @param clientOrUser - the appData to resolve - false for client, true for user appdata.
- * @return null or the DataInputStream desired.
- */
- private DataInput _getappdataInputStream(boolean clientOrUser) {
- if (clientdoc==null)
- throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
- String appdName;
- if (!clientOrUser) {
- appdName = "Client's Appdata";
- } else {
- appdName = "User's Appdata";
- }
- if (log.isDebugEnabled())
- log.debug("getting "+appdName+" as an input stream.");
- extractAppData(clientdoc.getVamsasDocument());
- AppData object;
- if (!clientOrUser) {
- object = appsGlobal;
- } else {
- object = usersData;
- }
- if (object!=null) {
- log.debug("Trying to resolve ClientAppdata object to an input stream.");
- return getAppDataAsDataInputStream(object, clientdoc.getVamsasArchiveReader());
- }
- log.debug("getClientInputStream returning null.");
- return null;
- }
- /* (non-Javadoc)
- * @see org.vamsas.client.IClientAppdata#getClientAppdata()
- */
- public byte[] getClientAppdata() {
- return _getappdataByteArray(false);
- }
- /* (non-Javadoc)
- * @see org.vamsas.client.IClientAppdata#getClientInputStream()
- */
- public DataInput getClientInputStream() {
- return _getappdataInputStream(false);
- }
-
- /* (non-Javadoc)
- * @see org.vamsas.client.IClientAppdata#getUserAppdata()
- */
- public byte[] getUserAppdata() {
- return _getappdataByteArray(true);
- }
-
- /* (non-Javadoc)
- * @see org.vamsas.client.IClientAppdata#getUserInputStream()
- */
- public DataInput getUserInputStream() {
- return _getappdataInputStream(true);
- }
- /**
- * methods for writing new AppData entries.
- */
- private DataOutput _getAppdataOutputStream(boolean clientOrUser) {
- String apdname;
- SessionFile apdfile=null;
- if (!clientOrUser) {
- apdname = "clientAppData";
- apdfile = newAppData;
- } else {
- apdname = "userAppData";
- apdfile = newUserData;
- }
- try {
- if (apdfile==null) {
- apdfile=clientdoc.sclient._session.getTempSessionFile(apdname,".jar");
- log.debug("Successfully made temp appData file for "+apdname);
- } else {
- // truncate to remove existing data.
- apdfile.fileLock.getRaFile().setLength(0);
- log.debug("Successfully truncated existing temp appData for "+apdname);
- }
- } catch (Exception e) {
- log.error("Whilst opening temp file in directory "+clientdoc.sclient._session.sessionDir, e);
- }
- // we do not make another file for the new entry if one exists already
- if (!clientOrUser) {
- newAppData = apdfile;
- } else {
- newUserData = apdfile;
- }
- try {
- apdfile.lockFile();
- // LATER: Refactor these local AppDatastream IO stuff to their own class.
- JarOutputStream dstrm =
- new JarOutputStream(apdfile.fileLock.getBufferedOutputStream(true));
- if (!clientOrUser) {
- newAppDataStream = dstrm;
- } else {
- newUserDataStream = dstrm;
- }
- dstrm.putNextEntry(new JarEntry("appData_entry.dat"));
- // LATER: there may be trouble ahead if an AppDataOutputStream is written to by one thread when another truncates the file. This situation should be prevented if possible
- return new AppDataOutputStream(dstrm);
- }
- catch (Exception e) {
- log.error("Whilst opening jar output stream for file "+apdfile.sessionFile);
- }
- // tidy up and return null
- apdfile.unlockFile();
- return null;
- }
- /**
- * copy data from the appData jar file to an appropriately
- * referenced jar or Data entry for the given ApplicationData
- * Assumes the JarFile is properly closed.
- * @param vdoc session Document handler
- * @param appd the AppData whose block is being updated
- * @param apdjar the new data in a Jar written by this class
- */
- protected void updateAnAppdataEntry(VamsasArchive vdoc, AppData appd, SessionFile apdjar) throws IOException {
- if (apdjar==null || apdjar.sessionFile==null || !apdjar.sessionFile.exists()) {
- throw new IOException("No temporary Appdata to recover and transfer.");
- }
- if (vdoc==null) {
- log.fatal("FATAL! NO DOCUMENT TO WRITE TO!");
- throw new IOException("FATAL! NO DOCUMENT TO WRITE TO!");
- }
- log.debug("Recovering AppData entry from "+apdjar.sessionFile);
- JarInputStream istrm = new JarInputStream(apdjar.getBufferedInputStream(true));
- JarEntry je=null;
- while (istrm.available()>0 && (je=istrm.getNextJarEntry())!=null && !je.getName().equals("appData_entry.dat")) {
- if (je!=null)
- log.debug("Ignoring extraneous entry "+je.getName());
- }
- if (istrm.available()>0 && je!=null) {
- log.debug("Found appData_entry.dat in Jar");
- String ref = appd.getDataReference();
- if (ref==null) {
- throw new IOException("Null AppData.DataReference passed.");
- }
- if (vdoc.writeAppdataFromStream(ref, istrm)) {
- log.debug("Entry updated successfully.");
- } else {
- throw new IOException("writeAppdataFromStream did not return true - expect future badness."); // LATER - verify why this might occur.
- }
- } else {
- throw new IOException("Couldn't find appData_entry.dat in temporary jar file "+apdjar.sessionFile.getAbsolutePath());
- }
- istrm.close();
- }
- /* (non-Javadoc)
- * @see org.vamsas.client.IClientAppdata#getClientOutputStream()
- */
- public DataOutput getClientOutputStream() {
- if (clientdoc==null)
- throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
- if (log.isDebugEnabled())
- log.debug("trying to getClientOutputStream for "+clientdoc.sclient.client.getClientUrn());
- return _getAppdataOutputStream(false);
- }
-
- /* (non-Javadoc)
- * @see org.vamsas.client.IClientAppdata#getUserOutputStream()
- */
- public DataOutput getUserOutputStream() {
- if (clientdoc==null)
- throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
- if (log.isDebugEnabled())
- log.debug("trying to getUserOutputStream for ("
- +clientdoc.sclient.getUserHandle().getFullName()+")"+clientdoc.sclient.client.getClientUrn());
- return _getAppdataOutputStream(true);
- }
-
- /* (non-Javadoc)
- * @see org.vamsas.client.IClientAppdata#hasClientAppdata()
- */
- public boolean hasClientAppdata() {
- if (clientdoc==null)
- throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
- extractAppData(clientdoc.getVamsasDocument());
- // LATER - check validity of a DataReference before we return true
- if ((appsGlobal!=null) && (appsGlobal.getDataReference()!=null || appsGlobal.getData()!=null))
- return true;
- return false;
- }
-
- /* (non-Javadoc)
- * @see org.vamsas.client.IClientAppdata#hasUserAppdata()
- */
- public boolean hasUserAppdata() {
- if (clientdoc==null)
- throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
- extractAppData(clientdoc.getVamsasDocument());
- // LATER - check validity of a DataReference before we return true
- if ((appsGlobal!=null) && (appsGlobal.getDataReference()!=null || appsGlobal.getData()!=null))
- return true;
- return false;
- }
- private boolean _writeAppDataStream(JarOutputStream ostrm, byte[] data) {
- try {
- if (data!=null && data.length>0)
- ostrm.write(data);
- ostrm.closeEntry();
- return true;
- }
- catch (Exception e) {
- log.error("Serious! - IO error when writing AppDataStream to file "+newAppData.sessionFile, e);
- }
- return false;
- }
- /* (non-Javadoc)
- * @see org.vamsas.client.IClientAppdata#setClientAppdata(byte[])
- */
- public void setClientAppdata(byte[] data) {
- if (clientdoc==null)
- throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
- _getAppdataOutputStream(false);
- if (newAppDataStream==null) {
- // LATER: define an exception for this ? - operation may fail even if file i/o not involved
- log.error("Serious! - couldn't open new AppDataStream in session directory "+clientdoc.sclient._session.sessionDir);
- } else {
- _writeAppDataStream(newAppDataStream, data);
- // LATER: deal with error case - do we make session read only, or what ?
- }
- }
-
- /* (non-Javadoc)
- * @see org.vamsas.client.IClientAppdata#setUserAppdata(byte[])
- */
- public void setUserAppdata(byte[] data) {
- if (clientdoc==null)
- throw new Error("Implementation error, Improperly initialized SimpleClientAppdata.");
- _getAppdataOutputStream(true);
- if (newUserDataStream==null) {
- // LATER: define an exception for this ? - operation may fail even if file i/o not involved
- log.error("Serious! - couldn't open new UserDataStream in session directory "+clientdoc.sclient._session.sessionDir);
- } else {
- _writeAppDataStream(newUserDataStream, data);
- // LATER: deal with error case - do we make session read only, or what ?
- }
- }
- /**
- * flush and close outstanding output streams.
- * - do this before checking data length.
- * @throws IOException
- */
- protected void closeForWriting() throws IOException {
- if (newAppDataStream!=null) {
- newAppDataStream.flush();
- newAppDataStream.closeEntry();
- newAppDataStream.close();
- }
- if (newUserDataStream!=null) {
- newUserDataStream.flush();
- newUserDataStream.closeEntry();
- newUserDataStream.close();
- }
- }
-
-
- /**
- *
- * @return true if any AppData blocks have to be updated in session Jar
- */
- protected boolean isModified() {
- // LATER differentiate between core xml modification and Jar Entry modification.
- if (newAppData.sessionFile.exists() || newUserData.sessionFile.exists())
- return true;
- return false;
- }
- /* (non-Javadoc)
- * @see java.lang.Object#finalize()
- */
- protected void finalize() throws Throwable {
- if (newAppDataStream!=null) {
- newAppDataStream = null;
- }
- if (newAppDataStream!=null) {
- newUserDataStream = null;
- }
- if (newAppData!=null) {
- newAppData.eraseExistence();
- newAppData = null;
- }
- if (newUserData!=null) {
- newUserData.eraseExistence();
- newUserData = null;
- }
- super.finalize();
- }
-
-}
+++ /dev/null
-/*
-* 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;
-
-/**
- *
- *
- */
-public class SimpleClientFactory implements IClientFactory {
-
- private static Log log = LogFactory.getLog(SimpleClientFactory.class);
-
- 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() 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 path to directory called session arena, where will be created session directories and session files.
- */
- 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 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));
- }
- }
-
- /**
- * 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()
- {
- 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;
- }
-
-
- 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 {
-
- return this.getIClient(applicationHandle, (UserHandle) null);
- }
-
- /**
- * @see org.vamsas.client.IClientFactory#getIClient(org.vamsas.client.ClientHandle, java.lang.String)
- */
- public IClient getIClient(ClientHandle applicationHandle, String sessionUrn) {
- // TODO Auto-generated method stub
- return null;
- }
-
- /**
- * @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) {
- // TODO Auto-generated method stub
- return null;
- }
-
- /**
- * @see org.vamsas.client.IClientFactory#getIClient(org.vamsas.client.ClientHandle, org.vamsas.client.UserHandle)
- */
- 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;
- }
-
-
- /**
- * @return the sessionFile
- */
- private SessionsFile getSessionFile() throws IOException
- {
- if (this.sessionFile == null)
- {
- this.sessionFile = new SessionsFile( new File (this.sessionArena, SESSION_LIST));
- }
- return this.sessionFile;
- }
-
-
-
-}
+++ /dev/null
-package org.vamsas.client.simpleclient;
-
-import java.io.BufferedInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.Vector;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.vamsas.client.Vobject;
-import org.vamsas.client.VorbaIdFactory;
-import org.vamsas.client.VorbaXmlBinder;
-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;
-
-/**
- * Base class for SimpleClient Vamsas Document Object Manipulation
- * holds static vamsasDocument from XML routines and
- * state objects for a particular unmarshalled Document instance.
- * @author jimp
- */
-
-
-public class SimpleDocBinding {
-
- protected VorbaIdFactory vorba;
- protected static Log log = LogFactory.getLog(SimpleDocBinding.class);
-
- /**
- * @return Returns the vorba.
- */
- public VorbaIdFactory getVorba() {
- return vorba;
- }
-
- /**
- * @param vorba The vorba to set.
- */
- public void setVorba(VorbaIdFactory vorba) {
- this.vorba = vorba;
- }
-
- /**
- * Uses VorbaXmlBinder to retrieve the VamsasDocument from the given stream
- */
- public VamsasDocument getVamsasDocument(VamsasArchiveReader oReader) throws IOException, org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException {
- if (oReader!=null) {
- // check the factory
- if (vorba==null) {
- log.error("Invalid SimpleDocument construction - no VorbaIdFactory defined!");
- return null;
- }
-
- if (oReader.isValid()) {
- // Read vamsasDocument.xsd instance
- InputStreamReader vdoc = new InputStreamReader(oReader.getVamsasDocumentStream());
- Object unmarsh[] = VorbaXmlBinder.getVamsasObjects(vdoc, vorba, new VamsasDocument());
- if (unmarsh==null)
- log.fatal("Couldn't unmarshall document!");
-
- Vobject vobjs = (Vobject) unmarsh[0];
- if (vobjs!=null) {
- VamsasDocument doc=(VamsasDocument) vobjs;
- if (doc!=null)
- return doc;
- }
- log.debug("Found no VamsasDocument object in properly formatted Vamsas Archive.");
- } else {
- // deprecated data handler (vamsas.xsd instance)
- 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(
- vorba.getUserHandle().getFullName(),
- "Vamsas Document constructed from vamsas.xml"), VersionEntries.ALPHA_VERSION);
- // VAMSAS: decide on 'system' operations provenance form
- // LATER: implement classes for translating Vorba properties into provenance user fields.
- // VAMSAS: decide on machine readable info embedding in provenance should be done
- root[0]=null;
- root=null;
- return doc;
- }
- }
- }
- }
- // otherwise - there was no valid original document to read.
- return null;
- }
-
- /**
- * Extract all jarEntries in an archive referenced by the vamsas document
- * LATER: a family of methods for finding extraneous jarEntries , and invalid appDataReferences
- * @param doc
- * @param oReader
- * @return array of the subset of JarEntry names that are referenced in doc
- */
- public Vector getReferencedEntries(VamsasDocument doc, VamsasArchiveReader oReader) {
- if (oReader==null)
- return null;
- if (doc==null) {
- try { doc = getVamsasDocument(oReader); }
- catch (Exception e) { log.warn("Failed to get document from "+oReader.jfile.getName()); };
- }
- Vector docrefs = AppDataReference.getAppDataReferences(doc);
- if (docrefs==null)
- return null;
- Vector entries = oReader.getExtraEntries();
- if (entries!=null && docrefs.size()>0) {
- int i=0, j=entries.size();
- do {
- if (!docrefs.contains(entries.get(i))) {
- entries.remove(i);
- j--;
- } else
- i++;
- } while (i<j);
- }
- return entries;
- }
-}
+++ /dev/null
-package org.vamsas.client.simpleclient;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.vamsas.client.VorbaIdFactory;
-
-/**
- * @see SimpleDocBinding
- * Additional constructors for 'headless' Vamsas Document access
- * @author jimp
- */
-public class SimpleDocument extends SimpleDocBinding {
- private static Log log = LogFactory.getLog(SimpleDocument.class);
-
- private VorbaIdFactory makeDefaultFactory(String name) {
- return IdFactory.getDummyFactory(name);
- }
-
- public SimpleDocument(String name) {
- vorba = makeDefaultFactory(name);
- }
- public SimpleDocument(VorbaIdFactory Vorba) {
- if (Vorba!=null)
- vorba = Vorba;
- else
- log.error("Invalid SimpleDocument construction - no VorbaIdFactory defined!");
- }
-}
+++ /dev/null
-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.InputStream;
-import java.io.InputStreamReader;
-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;
-import java.util.jar.Manifest;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.vamsas.client.ClientHandle;
-import org.vamsas.client.IVorbaIdFactory;
-import org.vamsas.client.SessionHandle;
-import org.vamsas.client.UserHandle;
-import org.vamsas.client.VorbaIdFactory;
-import org.vamsas.client.VorbaXmlBinder;
-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;
-
-/**
- * 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
- *
- */
-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;
- /**
- * original archive file to be updated (or null if virgin) where new data will finally reside
- */
- java.io.File original=null;
- /**
- * original archive IO handler
- */
- SessionFile odoclock = null;
- Lock destinationLock = null;
- /**
- * Original archive reader class
- */
- VamsasArchiveReader odoc = null;
- /**
- * true if a real vamsas document is being written.
- */
- boolean vamsasdocument=true;
- /**
- * Output stream for archived data
- */
- JarOutputStream newarchive=null;
- /**
- * 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.
- * only 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;
- /**
- * LATER: ? CUT'n'Paste error ?
- * 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
- * ????? where does this live JBPNote ?
- */
- private VamsasDocument _doc=null;
-
- /**
- * Create a new vamsas archive
- * 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) throws IOException {
- this(archive, false, vamsasdocument, null);
- }
- public VamsasArchive(File archive, boolean vamsasdocument, boolean overwrite) throws IOException {
- this(archive, overwrite, vamsasdocument, null);
- }
- /**
- * Constructor for accessing Files under file-lock management (ie a session file)
- * @param archive
- * @param vamsasdocument
- * @param overwrite
- * @throws IOException
- */
- public VamsasArchive(VamsasFile archive, boolean vamsasdocument, boolean overwrite) throws IOException {
- this(archive.sessionFile, overwrite, vamsasdocument, archive);
- // log.debug("using non-functional lock-IO stream jar access constructor");
- }
- /**
- * read and write to archive - will not overwrite original contents, and will always write an up to date vamsas document structure.
- * @param archive
- * @throws IOException
- */
- public VamsasArchive(VamsasFile archive) throws IOException {
- this(archive, true, false);
- }
- /**
- *
- * @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 <object>archive</object>
- * @throws IOException
- */
- public VamsasArchive(File archive, boolean overwrite, boolean vamsasdocument, SessionFile extantLock) throws IOException {
- super();
- if (archive==null || (archive!=null && !(archive.getAbsoluteFile().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() && !overwrite) {
- this.original = archive;
- if (extantLock!=null) {
- this.odoclock = extantLock;
- if (odoclock.fileLock==null || !odoclock.fileLock.isLocked())
- odoclock.lockFile();
- } 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 {
- 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.
- if (extantLock!=null)
- rchive=extantLock;
- else
- rchive = new SessionFile(archive);
- rchive.lockFile();
- if (rchive.fileLock==null || !rchive.fileLock.isLocked())
- throw new IOException("Lock failed for new archive"+archive);
- rchive.fileLock.getRaFile().setLength(0); // empty the archive.
- virginArchive = true;
- }
- this.openArchive(); // open archive
- }
- /**
- * open original archive file for exclusive (locked) reading.
- * @throws IOException
- */
- 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);
- // this constructor is not implemented yet odoc = new VamsasArchiveReader(odoclock.fileLock);
- }
- }
-
- /**
- * Add unique entry strings to internal JarEntries list.
- * @param entry
- * @return true if entry was unique and was added.
- */
- private boolean addEntry(String entry) {
- if (entries!=null)
- entries=new Hashtable();
- if (entries.containsKey(entry))
- return false;
- entries.put(entry, new Integer(entries.size()));
- return true;
- }
- /**
- * adds named entry to newarchive or returns false.
- * @param entry
- * @return true if entry was unique and could be added
- * @throws IOException if entry name was invalid or a new entry could not be made on newarchive
- */
- private boolean addValidEntry(String entry) throws IOException {
- JarEntry je = new JarEntry(entry);
- if (!addEntry(entry))
- return false;
- newarchive.flush();
- newarchive.putNextEntry(je);
- return true;
- }
- /**
- * 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
- */
- public File backupFile() {
-
- if (!virginArchive) {
- makeBackup();
- donotdeletebackup=false; // external reference has been made.
- return ((original!=null) ? originalBackup : null);
- }
- return null;
- }
-
- /**
- * Stops any current write to archive, and reverts to the backup if it exists.
- * All existing locks on the original will be released. All backup files are removed.
- */
- public boolean cancelArchive() {
- if (newarchive!=null) {
- try {
- newarchive.closeEntry();
- newarchive.putNextEntry(new JarEntry("deleted"));
- newarchive.closeEntry();
- newarchive.close();
-
- } catch (Exception e) {
- log.debug("Whilst closing newarchive",e);
- };
- if (!virginArchive) {
- // then there is something to recover.
- try {
- recoverBackup();
- }
- catch (Exception e) {
- log.warn("Problems when trying to cancel Archive "+archive.getAbsolutePath(), e);
- return false;
- }
- }
-
- } else {
- log.warn("Client Error: cancelArchive called before archive("+original.getAbsolutePath()+") has been opened!");
- }
- closeAndReset(); // tidy up and release locks.
- return true;
- }
-
- /**
- * only do this if you want to destroy the current file output stream
- *
- */
- private void closeAndReset() {
- if (rchive!=null) {
- rchive.unlockFile();
- rchive=null;
- }
- if (original!=null) {
- if (odoc!=null) {
- odoc.close();
- odoc=null;
- }
- if (archive!=null)
- archive.delete();
- if (odoclock!=null) {
- odoclock.unlockFile();
- odoclock = null;
- }
- }
- removeBackup();
- newarchive=null;
- original=null;
- entries=null;
- }
- /**
- * 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.flush();
- newarchive.closeEntry();
- if (!isDocumentWritten())
- log.warn("Premature closure of archive '"+archive.getAbsolutePath()+"': No document has been written.");
- newarchive.finish();// close(); // use newarchive.finish(); for a stream IO
- newarchive.flush();
- //
- 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 LATER - pass existing lock on document, if it exists.... no need yet?
- * @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);
- // LATER: locked IO stream based access.
- Manifest newmanifest = new Manifest();
- newarchive = new JarOutputStream(rchive.fileLock.getBufferedOutputStream(true), newmanifest);
- //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());
- }
- /**
- *
- * @param doc
- * @param vorba
- * @return (vorbaId string, Vobjhash) pairs for last hash of each object in document
- * @throws IOException
- * @throws org.exolab.castor.xml.MarshalException
- * @throws org.exolab.castor.xml.ValidationException
- */
- public void putVamsasDocument(VamsasDocument doc, VorbaIdFactory vorba) throws IOException,
- org.exolab.castor.xml.MarshalException, org.exolab.castor.xml.ValidationException {
- if (vamsasdocument)
- doc.setVersion(VersionEntries.latestVersion()); // LATER: ensure this does the correct thing.
- 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.
- * Duplicate writes return true - but a warning message will also be raised.
- * @param AppDataReference
- * @return true if AppDataReference now exists in the new document
- * @throws IOException
- */
- public boolean transferAppDataEntry(String AppDataReference) throws IOException {
- return transferAppDataEntry(AppDataReference, AppDataReference);
- }
- /**
- * Validates the AppDataReference: not null and not already written to archive.
- * @param AppDataReference
- * @return true if valid. false if not
- * @throws IOException for really broken references!
- */
- protected boolean _validNewAppDataReference(String newAppDataReference) throws IOException {
- // LATER: Specify valid AppDataReference form in all VamsasArchive handlers
- if (newAppDataReference==null)
- throw new IOException("null newAppDataReference!");
- if (entries.containsKey(newAppDataReference)) {
- log.warn("Attempt to write '"+newAppDataReference+"' twice! - IGNORED");
- // LATER: fix me? warning message should raise an exception here.
- return false;
- }
- return true;
- }
- /**
- * 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 {
- if (original==null || !original.exists()) {
- log.warn("No backup archive exists.");
- return false;
- }
- if (AppDataReference==null)
- throw new IOException("null AppDataReference!");
-
- if (!_validNewAppDataReference(NewAppDataReference))
- return false;
-
- accessOriginal();
-
- java.io.InputStream adstream = odoc.getAppdataStream(AppDataReference);
-
- if (adstream==null) {
- log.warn("AppDataReference '"+AppDataReference+"' doesn't exist in backup archive.");
- return false;
- }
-
- java.io.OutputStream adout = getAppDataStream(NewAppDataReference);
- // copy over the bytes
- int written=-1;
- long count=0;
- byte[] buffer = new byte[_TRANSFER_BUFFER]; // conservative estimate of a sensible buffer
- do {
- if ((written = adstream.read(buffer))>-1) {
- adout.write(buffer, 0, written);
- log.debug("Transferring "+written+".");
- count+=written;
- }
- } while (written>-1);
- log.debug("Sucessfully transferred AppData for '"
- +AppDataReference+"' as '"+NewAppDataReference+"' ("+count+" bytes)");
- return true;
- }
- /**
- * write data from a stream into an appData reference.
- * @param AppDataReference - New AppDataReference not already written to archive
- * @param adstream Source of data for appData reference - read until .read(buffer) returns -1
- * @return true on success.
- * @throws IOException for file IO or invalid AppDataReference string
- */
- public boolean writeAppdataFromStream(String AppDataReference, java.io.InputStream adstream) throws IOException {
- if (!_validNewAppDataReference(AppDataReference)) {
- log.warn("Invalid AppDataReference passed to writeAppdataFromStream");
- throw new IOException("Invalid AppDataReference! (null, or maybe non-unique)!");
- }
-
- if (AppDataReference==null) {
- log.warn("null appdata passed.");
- throw new IOException("Null AppDataReference");
- }
-
- java.io.OutputStream adout = getAppDataStream(AppDataReference);
- // copy over the bytes
- int written=-1;
- long count=0;
- byte[] buffer = new byte[_TRANSFER_BUFFER]; // conservative estimate of a sensible buffer
- do {
- if ((written = adstream.read(buffer))>-1) {
- adout.write(buffer, 0, written);
- log.debug("Transferring "+written+".");
- count+=written;
- }
- } while (written>-1);
- return true;
- }
- /**
- * transfers any AppDataReferences existing in the old document
- * that haven't already been transferred to the new one
- * LATER: do the same for transfers requiring a namechange - more document dependent.
- * @return true if data was transferred.
- */
- public boolean transferRemainingAppDatas() throws IOException {
- boolean transfered=false;
- if (original==null || !original.exists()) {
- log.warn("No backup archive exists.");
- return false;
- }
- 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 transfered;
- }
- /**
- * called after archive is written to put file in its final place
- */
- 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
- makeBackup();
- try {
- // copy new Archive data that was writen to a temporary file
- odoclock.updateFrom(null, rchive);
- }
- catch (IOException e) {
- // LATER: decide if leaving nastily named backup files around is necessary.
- File backupFile=backupFile();
- if (backupFile!=null)
- log.error("Problem updating archive from temporary file! - backup left in '"
- +backupFile().getAbsolutePath()+"'",e);
- else
- log.error("Problems updating, and failed to even make a backup file. Ooops!", e);
- }
- // Tidy up if necessary.
- removeBackup();
- } else {
-
-
- }
- }
-}
+++ /dev/null
-package org.vamsas.client.simpleclient;
-
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.BufferedInputStream;
-import java.io.FileInputStream;
-import java.io.RandomAccessFile;
-import java.util.Enumeration;
-import java.util.Hashtable;
-import java.util.Iterator;
-import java.util.Vector;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import java.util.jar.JarInputStream;
-import java.util.jar.JarOutputStream;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipInputStream;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.vamsas.objects.utils.document.VersionEntries;
-/**
- * Basic methods for accessing an existing Vamsas Archive,
- * and Jar entry names for creating new vamsas archives.
- *
- * @author jimp
- *
- */
-public class VamsasArchiveReader {
- private static Log log = LogFactory.getLog(VamsasArchiveReader.class);
- JarFile jfile=null;
- boolean stream=false; // true if we are seeking on the stream.
- RandomAccessFile rfile;
- ZipInputStream jstream=null;
- Hashtable strmentries = null;
- private void streamInit() {
- //throw new Error("VamsasArchiveReader(Stream) Not implemented!");
- if (!stream) {
- log.debug("Skipping init for Jar Stream input.");
- return;
- }
- strmentries = new Hashtable();
- log.debug("Jar Stream input Initialisation");
- try {
- rfile.seek(0);
- // no buffering - we need to be able to move around the random access stream.
- jstream = new ZipInputStream(new FileInputStream(rfile.getFD())); // no manifest (probably)
- if (jstream.available()==0)
- log.warn("Can't read from JarInputStream (Locked stream!)");
- ZipEntry entry=null;
- long pos=0;
- do {
- if ((entry=jstream.getNextEntry())!=null) {
- if (strmentries.containsKey(entry.getName())) {
- log.info("Only recording last of duplicate entries '"+entry.getName()+"'");
- }
- strmentries.put(entry.getName(), new Long(pos++));
- jstream.closeEntry();
- }
- } while (entry!=null);
- }
- catch (Exception e) {
- log.warn("Exceptions during init!",e);
- jstream=null;
- }
- }
-
- public VamsasArchiveReader(File vamsasfile) {
- jfile=null;
- if (vamsasfile.exists()) {
- try {
- jfile=new JarFile(vamsasfile);
- }
- catch (Exception e) {
- log.debug("non-serious? couldn't open new JarFile on "+vamsasfile,e);
- jfile=null;
- }
- }
-
- }
- /**
- * in an ideal world - this constructor will create a reader object
- * for the locked file's random access stream.
- *
- * @param vamsaslock
- */
- public VamsasArchiveReader(Lock vamsaslock) {
- // LATER: implement or remove
- if (vamsaslock==null || !vamsaslock.isLocked())
- throw new Error("IMPLEMENTATION ERROR: Cannot create a VamsasArchiveReader without a valid lock.");
- // throw new Error("VamsasArchiveReading from locked IO stream not yet implemented.");
- try {
- rfile = vamsaslock.getRaFile();
- } catch (Exception e) {
- log.warn("Unexpected IO Exception when accessing locked vamsas archive stream "+vamsaslock.target,e);
- }
- stream = true;
- streamInit();
- if (jstream==null)
- throw new Error("Failed to open archive from Locked random access stream.");
- }
-
- /**
- * the vamsas document version(s) handled by this Reader
- */
- final public static String DOCUMENT_VERSION=VersionEntries.BETA_VERSION;
- /**
- * name of the jarEntry containing a well formatted vamsas XML Document
- */
-
- final public static String VAMSASDOC="vamsasDocument.xml";
-
- /**
- * name of the jarEntry containing a root VAMSAS element, and containing a
- * random sequence of VAMSAS DataSet elements
- */
-
- final public static String VAMSASXML="vamsas.xml";
- /**
- * seeks jstream to the given entry name and reads it.
- * @param entryname
- * @return
- */
- private JarEntry seekEntry(String entryname) {
- if (jstream==null)
- return null;
- if (!strmentries.containsKey(entryname))
- return null;
- Long entrypos = (Long) strmentries.get(entryname);
- if (entrypos==null) {
- log.error("Null entry position for "+entryname);
- return null;
- }
- try {
- jstream=null;
- rfile.seek(0);
- jstream = new ZipInputStream(new FileInputStream(rfile.getFD()));
- ZipEntry entry = null;
- long epos = entrypos.longValue();
- do {
- entry = jstream.getNextEntry();
- } while (entry!=null && --epos>=0);
- // rfile.seek(entrypos.longValue());
- // make a Jar entry from a zip entry.
- return new JarEntry(entry);
- }
- catch (Exception e) {
- log.warn("Whilst seeking for "+entryname, e);
- }
- return null;
- }
- /**
- *
- * @return JarEntry for VamsasArchiveReader.VAMSASDOC
- */
- protected JarEntry getVamsasDocumentEntry() {
- return getJarEntry(VAMSASDOC);
- }
- /**
- *
- * @return JarEntry for VamsasArchiveReader.VAMSASXML
- */
- protected JarEntry getVamsasXmlEntry() {
- return getJarEntry(VAMSASXML);
- }
- /**
- * Test for valid vamsas document archive
- * @return true if getVamsasDocumentStream will return a stream likely to contain valid XML
- */
- public boolean isValid() {
- // TODO: check if VAMSASDOC is well formed (follows www.vamsas.ac.uk/schemas/vamsasDocument.xsd) and all appData references are resolvable - preferably as jar entries
- if (jfile!=null || jstream!=null)
- return (getVamsasDocumentEntry()!=null);
- return false;
- }
-
-
- protected JarEntry getAppdataEntry(String AppdataRef) {
- JarEntry entry;
- if ((jfile==null && jstream==null) || !isValid() || (entry=getJarEntry(AppdataRef))==null)
- return null;
-
- return entry;
- }
-
- public InputStream getAppdataStream(String AppdataRef) {
- JarEntry entry=getAppdataEntry(AppdataRef);
- try {
- if (entry!=null)
- return getInputStream(entry);
- } catch (IOException e) {
- log.error("Failed when opening AppdataStream for "+AppdataRef, e);
- }
- return null;
- }
- /**
- * get the VamsasDocument input stream, if it exists.
- * @return null or valid input stream
- */
- public InputStream getVamsasDocumentStream() {
- InputStream vdoc;
- if ((jfile==null && jstream==null) || !isValid())
- return null;
- try {
- vdoc = getInputStream(getVamsasDocumentEntry());
- } catch (IOException e) {
- log.error("Whilst geting document stream",e);
- vdoc=null;
- }
- return vdoc;
- }
-
- /**
- * get the VamsasXML input stream, if it exists.
- * Note: Deprecated beyond our prealpha testing.
- * @return null or valid input stream.
- */
-
- public InputStream getVamsasXmlStream() {
- // log.warn("Deprecated call");
- JarEntry xmle=getVamsasXmlEntry();
- InputStream vdoc;
- if (xmle==null)
- return null;
- try {
- vdoc = getInputStream(xmle);
- } catch (IOException e) {
- log.error("Whilst getting VamsasXmlStream",e);
- vdoc=null;
- }
- return vdoc;
- }
-
- /**
- * silently close the jar file.
- *
- */
- public void close() {
- if (jfile!=null) {
- try {
- jfile.close();
- } catch (IOException e) {
- log.error("Whilst closing JarFile "+jfile.getName(), e);
- }
- }
- if (jstream!=null) {
- try {
- jstream.closeEntry();
- jstream=null;
- // LATER: reference counting for random access file instances is necessary.
- }
- catch (Exception e) {
- log.error("Whilst finishing reading from jar input stream",e);
- }
- }
- }
-
- /**
- * returns all entries not matching the filespec of a vamsas xml entry
- * @return array of entries.
- */
- public Vector getExtraEntries() {
- if ((jfile==null && jstream==null)|| !isValid())
- return null;
- Vector e = new Vector();
- if (jstream!=null) {
- Enumeration entries = strmentries.keys();
- if (entries!=null && entries.hasMoreElements()) {
- do {
- JarEntry el = (JarEntry) entries.nextElement();
- if (!el.getName().equals(VAMSASDOC) && !el.getName().equals(VAMSASXML))
- e.add(new String(el.getName())); // avoid references
- } while (entries.hasMoreElements());
- }
- } else {
- Enumeration entries = jfile.entries();
- if (entries!=null && entries.hasMoreElements()) {
- do {
- JarEntry el = (JarEntry) entries.nextElement();
- if (!el.getName().equals(VAMSASDOC) && !el.getName().equals(VAMSASXML))
- e.add(new String(el.getName())); // avoid references
- } while (entries.hasMoreElements());
- }
- return e;
- }
- return null;
- }
-
- /* (non-Javadoc)
- * @see java.util.jar.JarFile#getInputStream(java.util.zip.ZipEntry)
- */
- private InputStream getInputStream(ZipEntry ze) throws IOException {
- if (jfile!=null)
- return jfile.getInputStream(ze);
- if (jstream!=null) {
- seekEntry(ze.getName());
- return new AppDataInputStream(jstream);
- }
- return null;
- }
-
- /* (non-Javadoc)
- * @see java.util.jar.JarFile#getJarEntry(java.lang.String)
- */
- private JarEntry getJarEntry(String name) {
- if (jfile!=null)
- return jfile.getJarEntry(name);
- if (jstream!=null)
- return seekEntry(name);
- return null;
- }
- }
+++ /dev/null
-
-package org.vamsas.client.simpleclient;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.FileReader;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.io.PrintWriter;
-import java.util.Timer;
-import java.util.jar.JarEntry;
-import java.util.jar.JarFile;
-import java.util.jar.JarInputStream;
-import java.util.jar.JarOutputStream;
-
-import org.vamsas.objects.core.LockFileDescriptor;
-
-/**
- * low level vamsas document management routines
- * analogous to ClientsFile
- * Grew out of io tests on VamsasArchive class in org.vamsas.test.simpleclient.VamsasArchive
- * This class is not thread safe.
- * @author jimp
- *
- */
-public class VamsasFile extends SessionFile {
- /**
- *
- * Connect to an existing Vamsas document in a given sessionDir
- * or create a new one.
- *
- * @param sessionDir
- * @throws java.io.IOException
- */
- public VamsasFile(File sessionFile) throws java.io.IOException {
- super(sessionFile);
- }
- /**
- *
- * @return the VamsasFile
- */
- public File getVamsasFile() {
- return sessionFile;
- }
- /**
- * Expand a previously stored session into the sessionDir
- * @param sessionDir
- * @param storedSession
-
- public VamsasFile(File sessionDir, JarFile storedSession) throws IOException {
- // check if sessionDir is live or not
- if (!sessionDir.exists()) {
- sessionDir.mkdir();
- }
-
- {
- // check its actually a writable directory
- }
-
- File sfile = new File(sessionDir, "vamsas.jar");
- VamsasFile(sfile);
- // if live - try to merge storedSession with sessionDir
- // - will probably fail through duplicate Vobject references needing to be dereferenced.
- // TODO: think of a way of specifying vorba_id scope for an application's references to allow merging of one vamsasDocument with another.
-
- }
- */
- /**
- * public interface for getting a lock.
- * The lock object is internally referenced
- * so the lock will persist even after the
- * return value of the method goes out of scope.
- * @return null if lock couldn't be got or a valid Lock object.
- */
- public Lock getLock() {
- if (lockFile())
- return fileLock;
- return null;
- }
- /**
- *
- * @param extantLock
- * @return null, extantLock or new Lock.
- */
- public Lock getLock(Lock extantLock) {
- if (lockFile(extantLock))
- return fileLock;
- return null;
- }
- /**
- * explicitly unlocks vamsas file.
- * if you have called getLock() you *must*
- * call this to release the lock.
- */
- public void unLock() {
- this.unlockFile();
- }
-
-}
+++ /dev/null
-package org.vamsas.client.simpleclient;
-
-import java.io.BufferedWriter;
-import java.io.File;
-import java.io.IOException;
-import java.io.PrintStream;
-import java.io.PrintWriter;
-import java.io.RandomAccessFile;
-import java.io.Writer;
-
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-import org.apache.log4j.Appender;
-import org.apache.log4j.Logger;
-import org.apache.log4j.FileAppender;
-import org.vamsas.client.ClientHandle;
-import org.vamsas.client.UserHandle;
-/**
- * Does all the IO operations for a SimpleClient instance accessing
- * a SimpleClient vamsas session.
- *
- * Basically, it defines the various standard names for the files
- * in the session directory (that maps to the sessionUrn),
- * provides constructors for the file handlers and watchers of
- * those file entities, and some higher level methods
- * to check and change the state flags for the session.
- *
- * TODO: move the stuff below to the SimpleClientFactory documentation.
- * much may not be valid now :
- * Vamsas client is intialised with a path to create live session directories.
- * This path may contain a vamsas.properties file
- * that sets additional parameters (otherwise client
- * just uses the one on the classpath).
- *
- * A vamsas session consists of :
- * SessionDir - translates to urn of a live session.
- * Contains: Vamsas Document (as a jar), Session client list file,
- * both of which may be locked, and additional
- * temporary versions of these files when write
- * operations are taking place.
- *
- * Zip file entries
- * - vamsasdocument.xml : core info
- * one or more:
- * - <applicationname>.version.sessionnumber.raw (string given in vamsasdocument.xml applicationData entry)
- *
- * Lockfile
- * - filename given in the vamsasdocument.xml. Should be checked for validity by any client and rewritten if necessary.
- * The lockfile can point to the jar itself.
- * Mode of operation.
- * Initially - documentHandler either:
- * - creates a zip for a new session for the client
- * - connect to an existing session zip
- * 1. reads session urn file
- * 2. waits for lock
- * 3. examines session - decide whether to create new application data slice or connect to one stored in session.
- * 4. writes info into session file
- * 5. releases lock and generates local client events.
- * 6. Creates Watcher thread to generate events.
- *
- * During the session
- * - Update watcher checks for file change -
- *
- * Procedures for file based session message exchange
- * - session document modification flag
- *
- */
-
-public class VamsasSession {
- /**
- * indicator file for informing other processes that
- * they should finalise their vamsas datasets for
- * storing into a vamsas archive.
- */
- public static final String CLOSEANDSAVE_FILE="stored.log";
- /**
- * session file storing the last_stored_stat data
- */
- public static final String MODIFIEDDOC_FILE="modified";
-
- /**
- * called to clear update flag after a successful offline storage event
- */
- protected void clearUnsavedFlag() {
- SessionFlagFile laststored = new SessionFlagFile(new File(sessionDir, MODIFIEDDOC_FILE));
- if (!laststored.clearFlag())
- log.warn("Unsaved flag was not cleared for "+sessionDir);
- }
- /**
- * called to indicate session document has been modified.
- *
- */
- protected void setUnsavedFlag() {
- SessionFlagFile laststored = new SessionFlagFile(new File(sessionDir, MODIFIEDDOC_FILE));
- if (!laststored.setFlag())
- log.warn("Couldn't set the Unsaved flag for "+sessionDir);
- }
- /**
- *
- * @return true if session document has been modified since last offline storage event
- */
- protected boolean getUnsavedFlag() {
- SessionFlagFile laststored = new SessionFlagFile(new File(sessionDir, MODIFIEDDOC_FILE));
- return laststored.checkFlag();
- }
- /**
- * log file location
- */
- public static final String SESSION_LOG="Log.txt";
- private static Log log = LogFactory.getLog(VamsasSession.class);
- protected Logger slog = Logger.getLogger("org.vamsas.client.SessionLog");
- /**
- * setup the sessionLog using Log4j.
- * @throws IOException
- */
- private void initLog() throws IOException {
- // LATER: make dedicated appender format for session log.
- Appender app = slog.getAppender("SESSION_LOG");
- slog.addAppender(new FileAppender(app.getLayout(), new File(sessionDir, SESSION_LOG).getAbsolutePath()));
- }
-
- /**
- * the sessionDir is given as the session location for new clients.
- */
- protected File sessionDir;
- /**
- * holds the list of attached clients
- */
- ClientsFile clist;
- public static final String CLIENT_LIST="Clients.obj";
- /**
- * holds the data
- */
- VamsasFile vamArchive;
- public static final String VAMSAS_OBJ="VamDoc.jar";
-
- /**
- * sets up the vamsas session files and watchers in sessionDir
- * @param sessionDir
- */
- protected VamsasSession(File sessionDir) throws IOException {
- if (sessionDir==null)
- throw new Error("Null directory for VamsasSession.");
- if (sessionDir.exists()) {
- if (!sessionDir.isDirectory() || !sessionDir.canWrite() || !sessionDir.canRead())
- throw new IOException("Cannot access '"+sessionDir+"' as a read/writable Directory.");
- if (checkSessionFiles(sessionDir)) {
- // session files exist in the directory
- this.sessionDir = sessionDir;
- initSessionObjects();
- slog.debug("Initialising additional VamsasSession instance");
- log.debug("Attached to VamsasSession in "+sessionDir);
- }
- } else {
- // start from scratch
- if (!sessionDir.mkdir())
- throw new IOException("Failed to make VamsasSession directory in "+sessionDir);
- this.sessionDir = sessionDir;
- createSessionFiles();
- initSessionObjects();
- slog.debug("Session directory created.");
- log.debug("Initialised VamsasSession in "+sessionDir);
- }
- }
- /**
- * tests presence of existing sessionfiles files in dir
- * @param dir
- * @return
- */
- private boolean checkSessionFiles(File dir) throws IOException {
- File c_file = new File(dir,CLIENT_LIST);
- File v_doc = new File(dir,VAMSAS_OBJ);
- if (c_file.exists() && v_doc.exists())
- return true;
- return false;
- }
- /**
- * create new empty files in dir
- *
- */
- private void createSessionFiles() throws IOException {
- if (sessionDir==null)
- throw new IOException("Invalid call to createSessionFiles() with null sessionDir");
- File c_file = new File(sessionDir,CLIENT_LIST);
- File v_doc = new File(sessionDir,VAMSAS_OBJ);
- if (c_file.createNewFile())
- log.debug("Created new ClientFile "+c_file); // don't care if this works or not
- if (v_doc.createNewFile())
- log.debug("Created new Vamsas Session Document File "+v_doc);
- }
- /**
- * construct SessionFile objects and watchers for each
- */
- private void initSessionObjects() throws IOException {
- if (clist!=null || vamArchive!=null)
- throw new IOException("initSessionObjects called for initialised VamsasSession object.");
- clist = new ClientsFile(new File(sessionDir,CLIENT_LIST));
- vamArchive = new VamsasFile(new File(sessionDir,VAMSAS_OBJ));
- initLog();
- }
- /**
- * make a new watcher object for the clientFile
- * @return new ClientFile watcher instance
- */
- public FileWatcher getClientWatcher() {
- return new FileWatcher(clist.sessionFile);
- }
- FileWatcher session_doc_watcher=null;
- /**
- * make a new watcher object for the vamsas Document
- * @return new ClientFile watcher instance
- */
- public FileWatcher getDocWatcher() {
- if (session_doc_watcher==null)
- return session_doc_watcher = new FileWatcher(vamArchive.sessionFile);
- return new FileWatcher(vamArchive.sessionFile);
- }
- FileWatcher store_doc_file=null;
- /**
- * make a new watcher object for the messages file
- * (thread safe - keeps a reference to the first watcher)
- * @return new watcher instance
- */
- public FileWatcher getStoreWatcher() {
- if (store_doc_file==null)
- return store_doc_file = new FileWatcher(new File(CLOSEANDSAVE_FILE));
- return new FileWatcher(new File(CLOSEANDSAVE_FILE));
-
- }
- /**
- * write to the StoreWatcher file to indicate that a storeDocumentRequest has been made.
- * The local client's storeWatcher FileWatcher object is updated so the initial change is not registered.
- * @param client
- * @param user
- * @return
- */
- public void addStoreDocumentRequest(ClientHandle client, UserHandle user) throws IOException {
- SessionFile sfw = new SessionFile(new File(sessionDir, CLOSEANDSAVE_FILE));
- while (!sfw.lockFile())
- log.debug("Trying to get lock for "+CLOSEANDSAVE_FILE);
- RandomAccessFile sfwfile=sfw.fileLock.getRaFile();
- sfwfile.setLength(0); // wipe out any old info.
- // TODO: rationalise what gets written to this file (ie do we want other clients to read the id of the requestor?)
- sfwfile.writeUTF(client.getClientUrn()+":"+user.getFullName()+"@"+user.getOrganization());
- sfw.unlockFile();
- if (store_doc_file!=null)
- store_doc_file.setState();
- slog.info("FinalizeAppData request from "+user.getFullName()+" using "+client.getClientUrn()+"");
- }
- /**
- * create a new session with an existing vamsas Document - by copying it into the session.
- * @param archive
- */
- public void setVamsasDocument(File archive) throws IOException {
- log.debug("Transferring vamsas data from "+archive+" to session:"+vamArchive.sessionFile);
- SessionFile xtantdoc = new SessionFile(archive);
- vamArchive.updateFrom(null, xtantdoc);
- // LATER: decide if session archive provenance should be updated to reflect access.
- // TODO: soon! do a proper import objects from external file
- log.debug("Transfer complete.");
- }
- /**
- * write session as a new vamsas Document (this will overwrite any existing file without warning)
- * TODO: test
- * TODO: verify that lock should be released for vamsas document.
- * @param destarchive
- */
- protected void writeVamsasDocument(File destarchive, Lock extlock) throws IOException {
- log.debug("Transferring vamsas data from "+vamArchive.sessionFile+" to session:"+destarchive);
- SessionFile newdoc = new SessionFile(destarchive);
- if (extlock==null && !vamArchive.lockFile())
- while (!vamArchive.lockFile())
- log.info("Trying to get lock for "+vamArchive.sessionFile);
- // TODO: LATER: decide if session archive provenance should be written in vamsasDocument file for this export.
- newdoc.updateFrom(extlock, vamArchive);
- // LATER: LATER: fix use of updateFrom for file systems where locks cannot be made (because they don't have a lockManager, ie NFS/Unix, etc).
- vamArchive.unLock();
- newdoc.unlockFile();
- log.debug("Transfer complete.");
- }
-
- /**
- * Creates a VamsasArchive Vobject for accessing and updating document
- * Note: this will lock the Vamsas Document for exclusive access to the client.
- * @return session vamsas document
- * @throws IOException if locks fail or vamsas document read fails.
- */
- protected VamsasArchive getVamsasDocument() throws IOException {
- // TODO: check we haven't already done this once
- if (!vamArchive.lockFile())
- throw new IOException("Failed to get lock for vamsas archive.");
-
- VamsasArchive va = new VamsasArchive(vamArchive.sessionFile, false, true, vamArchive);
-
- return va;
- }
- /**
- * create a uniquely named file in the session Directory
- * @see java.io.File.createTempFile
- * @param pref Prefix for name
- * @param suff Suffix for name
- * @return SessionFile object configured for the new file (of length zero)
- * @throws IOException
- */
- protected SessionFile getTempSessionFile(String pref, String suff) throws IOException {
- File tfile = File.createTempFile(pref,suff,sessionDir);
- SessionFile tempFile = new SessionFile(tfile);
- return tempFile;
- }
-}
-
-