*/
package org.vamsas.client.simpleclient;
-import java.util.Hashtable;
import java.util.Vector;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
-import org.vamsas.client.IClient;
+import org.vamsas.client.ClientHandle;
import org.vamsas.client.IClientAppdata;
import org.vamsas.client.IClientDocument;
-import org.vamsas.client.VorbaId;
import org.vamsas.client.Vobject;
-import org.vamsas.objects.core.AppData;
+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.
public boolean isModified() {
return isModified;
}
+ private java.util.Hashtable objrefs=null;
/**
*
* prepare Application-side dataset from the vamsas Document archive
this.sclient = sclient;
archive = docHandler;
this.doc = doc;
+ objrefs = Factory.getVorbaIdHash();
}
/*
* @see org.vamsas.client.IClientDocument#getObject(org.vamsas.client.VorbaId)
*/
public Vobject getObject(VorbaId id) {
- // TODO: look up id in document Vobject
- // retrieve Vobject and return
+ if (objrefs.containsKey(id))
+ return (Vobject) objrefs.get(id);
+ log.debug("Returning null Vobject reference for id "+id.getId());
return null;
}
* @see org.vamsas.client.IClientDocument#getObjects(org.vamsas.client.VorbaId[])
*/
public Vobject[] getObjects(VorbaId[] ids) {
- // TODO: getObject in bulk
- return null;
+ Vobject[] vo = new Vobject[ids.length];
+ for (int i=0,j=ids.length; i<j;i++)
+ if (objrefs.containsKey(ids[i]))
+ vo[i] = (Vobject) objrefs.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
* @return true if newVersion is a valid root that preserves original references
*/
private boolean isValidUpdate(VAMSAS newVersion, final VAMSAS oldVersion) {
- // LATER: IMPLEMENT
// 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.
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
/**
* 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) {
-
+ VAMSAS[] newr;
+ if (newroots==null) {
+ log.debug("setVamsasRoots(null) - do nothing.");
+ return;
+ }
// are we dealing with same array ?
if (_VamsasRoots!=newroots) {
- // merge roots into
- }
- // 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 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)
} else {
ids[i]=registerObject(unregistered[i]);
}
+ log.debug("Registered "+unregistered.length+" objects - total of "+objrefs.size()+" ids.");
return ids;
}
return null;
* @see org.vamsas.client.IClientDocument#registerObject(org.vamsas.client.Vobject)
*/
public VorbaId registerObject(Vobject unregistered) {
- if (unregistered!=null)
- return _registerObject(unregistered);
+ if (unregistered!=null) {
+ VorbaId id = _registerObject(unregistered);
+ log.debug("Registered object - total of "+objrefs.size()+" ids.");
+ return id;
+ }
log.warn("Null Vobject passed to registerObject.");
return null;
}
}
return scappd;
}
- /* (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;
- }
-
- super.finalize();
- }
/**
* access the vamsas document
* @return the session's vamsas document
}
return null;
}
+ protected boolean updateSessionDocument() throws java.io.IOException {
+ if (!isModified() && !scappd.isModified())
+ 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;
+ scappd.closeForWriting();
+ long newAppd = scappd.newAppData.sessionFile.length();
+
+ if (scappd.appsGlobal==null) {
+ 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()));
+ }
+ if (scappd.newAppData!=null && scappd.newAppData.sessionFile.exists()) {
+ if (scappd.appsGlobal.getData()!=null) {
+ scappd.appsGlobal.setData(null);
+ scappd.appsGlobal.setDataReference(AppDataReference.uniqueAppDataReference(doc, sclient.client.getClientUrn()));
+ }
+
+
+
+ }
+ if (scappd.usersData==null) {
+
+ }
+
+ }
+ cdocument.archive.putVamsasDocument(vdoc);
+ // write the appHandle to the lastupdate file.
+ }
+ if (scappd!=null) {
+ if (scappd.accessedDocument)
+ }
+ va = new org.vamsas.client.simpleclient.VamsasArchive(newf, false, true, sfile);
+ doc = va.getVamsasDocument();
+ doc.addVAMSAS(Core.getDemoVamsas());
+ doc.addApplicationData(makeDemoAppdata(va,
+ "org.vamsas.test.simpleclient.VamsasArchive", "another old Bugger esq", "rescinded"));
+ if (va.transferRemainingAppDatas())
+ log.info("Remain appdatas were transferred.");
+ else
+ log.warn("No appdatas were transferred. This is wrong.");
+ va.putVamsasDocument(doc);
+ va.closeArchive();
+
+ return true; // successfully updated.
+ }
+ /* (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;
+ }
+ // TODO local garbage collection
+ super.finalize();
+ }
+
}
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;
public UserHandle getUserHandle() {
return user;
}
-
+ /**
+ *
+ * @return user field for a provenance entry
+ */
+ protected String getProvenanceUser() {
+ return new String(user.getFullName()+" ["+client.getClientUrn()+"]");
+ }
+ /**
+ * construct a provenance entry for this client with the specified action string.
+ * @param action
+ * @return properly completed provenance entry
+ */
+ protected Entry getProvenanceEntry(String action) {
+ // VAMSAS: modify schema to allow referencing of user field (plus other issues, ClientUrn field, machine readable action, input parameters, additional data generated notes
+ Entry prov = ProvenanceStuff.newProvenanceEntry(getProvenanceUser(), action);
+ return prov;
+ }
private Hashtable handlers = initHandlers();
private Vector listeners = new Vector();
// if session currently holds data - read it in - or get a dummy
_session.slog.debug("Accessing document");
doc =
- va.getVamsasDocument(user.getFullName()+" using "+client.getClientName(),
+ va.getVamsasDocument(getProvenanceUser(),
"created new session document.", null);
if (doc!=null)
_session.slog.debug("Successfully retrieved document.");
/*
* (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.");
}
-
- // try to update the sessionFile
-
- // write the appHandle to the lastupdate file.
-
+ 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 {
+ if (cdocument.updateSessionDocument())
+ log.warn("Session document did not update properly for session directory "+_session.sessionDir);
+ }
+ // 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;
}
/*
import java.io.DataInputStream;
import java.io.DataOutput;
import java.io.DataOutputStream;
+import java.io.IOException;
import java.io.InputStream;
import java.util.Vector;
import java.util.jar.JarEntry;
*/
SessionFile newAppData=null;
JarOutputStream newAppDataStream=null;
+ /**
+ * set by extractAppData
+ */
+ protected ApplicationData appsGlobal = null;
+ /**
+ * set by extractAppData
+ */
+ protected User usersData = null;
+
ClientDocument clientdoc;
/**
* state flags
this.clientdoc = clientdoc;
}
/**
- * set by extractAppData
- */
- protected ApplicationData appsGlobal = null;
- /**
- * set by extractAppData
- */
- protected User usersData = null;
- /**
* 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.
*/
// 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();
+ }
+ }
+ /**
+ * copy data from the appData jar file to an appropriately
+ * referenced jar or Data entry for the given ApplicationData
+ * @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) {
+
+ }
+
+ /**
+ *
+ * @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()
*/