/* * 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.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.SessionHandle; import org.vamsas.client.UserHandle; import org.vamsas.objects.core.LockFile; import org.vamsas.objects.core.VamsasDocument; 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; /** * 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) { // TODO: validate user/client/session _session = sess; this.user = user; this.client = client; session = new SessionUrn(_session); } /** * 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; } 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 { VamsasArchive va = null; try { // TODO: 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(user.getFullName()+" using "+client.getClientName(), "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) * * @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. } /* * (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); } 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()"); 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."); } } /* (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 implemented for a SimpleClient Session."); } }