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.vamsas.client.Events;
import org.vamsas.client.IClient;
import org.vamsas.client.IClientDocument;
+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
protected VamsasSession _session;
protected ClientHandle client = null;
protected EventGeneratorThread evgen = null;
- IdFactory vorba = null;
- private void makeVorbaIdFactory() {
- if (vorba==null) {
- vorba = new IdFactory(getSessionHandle(), client, user);
- } else
- log.debug("Vorba Id factory exists already.");
+ protected ClientDocument cdocument = 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);
}
/**
* @param client
* @param sess
*/
- protected SimpleClient(UserHandle user, ClientHandle client, VamsasSession sess) {
+ protected SimpleClient(UserHandle user, ClientHandle client, VamsasSession sess) throws InvalidSessionUrnException {
// TODO: validate user/client/session
_session = sess;
this.user = user;
this.client = client;
- session = new SessionUrn(_session);
+ 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
*/
protected SimpleClient(UserHandle user, ClientHandle client, VamsasSession sess, File importingArchive) throws Exception {
this(user, client, sess);
- makeVorbaIdFactory();
VamsasArchive sessdoc = _session.getVamsasDocument();
try {
VamsasArchiveReader odoc = new VamsasArchiveReader(importingArchive);
- SimpleDocument sdoc = new SimpleDocument(vorba);
+ SimpleDocument sdoc = new SimpleDocument(makeVorbaIdFactory());
VamsasDocument doc = sdoc.getVamsasDocument(odoc);
- sessdoc.putVamsasDocument(doc, vorba);
+ 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)
- * TODO: LATER: check that build substitution variables are correct
+ * LATER: check that build substitution variables are correct
* @see org.vamsas.client.IClient#getAbout()
*/
public String getAbout() {
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();
// mark this instance as finalized
}
- /**
- * extract data appropriate for client, session and user
- * from vamsas document.
- * @return application's byte array
- */
- private byte[] getApplicationData() {
- // TODO: extract correct byte object from Jar and return it to application.
- return null;
- }
-
/*
* (non-Javadoc)
*
* @see org.vamsas.client.IClient#getClientDocument()
*/
public IClientDocument getClientDocument() throws IOException {
-
- makeVorbaIdFactory();
- VamsasArchive va = _session.getVamsasDocument();
+ 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.getOriginalVamsasDocument(va, vorba);
- // if session currently holds data - read it in.
+ 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+"'");
}
- //ClientDocument cdoc = new ClientDocument();
+ // Construct the IClientDocument instance
- Object[] vdoc;// TODO: = getVamsasDocument(new Reader());
- // ClientDocument cdoc = new ClientDocument(getApplicationData(),
- // ((VamsasDocument) vdoc[0]).getVAMSAS(), (Hashtable) vdoc[1], this);
- //
- return null;
+ 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.");
}
-
- // 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 {
+ 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;
}
/*
* @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();
}
* @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()");
+ 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()
*/
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);
+ }
}