2 * Created on 15-Sep-2005
4 * TODO To change the template for this generated file go to
5 * Window - Preferences - Java - Code Style - Code Templates
7 package org.vamsas.client.simpleclient;
9 import java.beans.EventHandler;
10 import java.beans.PropertyChangeEvent;
11 import java.beans.PropertyChangeListener;
12 import java.beans.PropertyChangeSupport;
13 import java.io.BufferedReader;
15 import java.io.IOException;
16 import java.net.MalformedURLException;
17 import java.util.Hashtable;
18 import java.util.Vector;
20 import org.apache.commons.logging.Log;
21 import org.apache.commons.logging.LogFactory;
22 import org.vamsas.client.ClientHandle;
23 import org.vamsas.client.Events;
24 import org.vamsas.client.IClient;
25 import org.vamsas.client.IClientDocument;
26 import org.vamsas.client.InvalidSessionUrnException;
27 import org.vamsas.client.SessionHandle;
28 import org.vamsas.client.UserHandle;
29 import org.vamsas.objects.core.LockFile;
30 import org.vamsas.objects.core.VamsasDocument;
31 import org.vamsas.objects.utils.ProvenanceStuff;
32 import org.vamsas.objects.utils.document.VersionEntries;
37 public class SimpleClient implements IClient {
39 private static Log log = LogFactory.getLog(SimpleClient.class);
41 protected UserHandle user = null;
43 protected SessionUrn session = null;
44 protected VamsasSession _session;
45 protected ClientHandle client = null;
46 protected EventGeneratorThread evgen = null;
47 protected ClientDocument cdocument = null;
49 * construct a transient IdFactory instance - this should last only as long as the
50 * SimpleClient object holds the lock on the vamsas document being created/manipulated.
53 private IdFactory makeVorbaIdFactory() {
54 return new IdFactory(getSessionHandle(), client, user);
58 * construct SimpleClient for user, client and VamsasSession directory
59 * use the SimpleClientFactory rather than this constructor directly.
64 protected SimpleClient(UserHandle user, ClientHandle client, VamsasSession sess) throws InvalidSessionUrnException {
65 // TODO: validate user/client/session
70 session = new SessionUrn(_session);
71 } catch (MalformedURLException e) {
72 log.error("Couldn't form a valid SessionUrn object!",e);
73 throw new InvalidSessionUrnException(_session.toString());
77 * construct new session by importing objects from an existing vamsas document
81 * @param importingArchive
82 * @throws Exception IOExceptions for Session IO problems, and general Exception if importing document is invalid.
84 protected SimpleClient(UserHandle user, ClientHandle client, VamsasSession sess, File importingArchive) throws Exception {
85 this(user, client, sess);
86 VamsasArchive sessdoc = _session.getVamsasDocument();
88 VamsasArchiveReader odoc = new VamsasArchiveReader(importingArchive);
89 SimpleDocument sdoc = new SimpleDocument(makeVorbaIdFactory());
90 VamsasDocument doc = sdoc.getVamsasDocument(odoc);
91 sessdoc.putVamsasDocument(doc, sdoc.vorba);
92 sessdoc.closeArchive();
93 } catch (Exception e) {
94 sessdoc.cancelArchive();
95 // write a dummy archive
96 _session.slog.info("Exception when importing document data from "+importingArchive);
97 throw new Exception("Failed to import data from "+importingArchive, e);
103 * LATER: check that build substitution variables are correct
104 * @see org.vamsas.client.IClient#getAbout()
106 public String getAbout() {
107 return new String("VORBA SimpleClient version $version$ build $build$");
113 * @see org.vamsas.client.IClient#getSessionUrn()
115 public String getSessionUrn() {
116 return session.getSessionUrn();
122 * @see org.vamsas.client.IClient#getSessionHandle()
124 public SessionHandle getSessionHandle() {
125 // TODO: eliminate SessionHandle ? need to refactor interfaces.
126 SessionHandle sh = new SessionHandle(session.getSessionUrn());
133 * @see org.vamsas.client.IClient#getClientHandle()
135 public ClientHandle getClientHandle() {
142 * @see org.vamsas.client.IClient#getUserHandle()
144 public UserHandle getUserHandle() {
148 private Hashtable handlers = initHandlers();
150 private Vector listeners = new Vector();
153 * make all the PropertyChangeSupport objects for the
154 * events described in org.vamsas.client.Event
157 private static Hashtable initHandlers() {
158 Hashtable events = new Hashtable();
159 java.util.Iterator evt = Events.EventList.iterator();
160 while (evt.hasNext()) {
161 Object ths = evt.next();
162 events.put(ths, (Object) new PropertyChangeSupport(ths));
170 * @see org.vamsas.client.IClient#addDocumentUpdateHandler(java.util.EventListener)
172 public void addDocumentUpdateHandler(PropertyChangeListener evt) {
173 if (handlers.containsKey(Events.DOCUMENT_UPDATE)) {
175 ((PropertyChangeSupport) (handler = handlers.get(Events.DOCUMENT_UPDATE)))
176 .addPropertyChangeListener(evt);
177 listeners.add(handler);
178 listeners.add((Object) evt);
181 boolean finalized=false;
185 * @see org.vamsas.client.IClient#finalizeClient()
187 public void finalizeClient() {
188 // TODO: determine if this is last client in session
189 // TODO: raise events like : ((lst_client && document.request.to.close), (client_finalization), (
191 // if (handlers.containsKey(Events.))
192 // if (handlers.containsKey(Events.CLIENT_FINALIZATION))
193 // deregister listeners.
194 // mark this instance as finalized
200 * @see org.vamsas.client.IClient#getClientDocument()
202 public IClientDocument getClientDocument() throws IOException {
203 if (cdocument!=null) {
204 // cdocument is non-nill if the ClientDocument.finalise() method hasn't been called.
207 VamsasArchive va = null;
209 // LATER: bail out if it takes too long to get the lock ?
210 va = _session.getVamsasDocument();
212 catch (IOException e) {
213 throw new IOException("Failed to get lock on session document");
215 VamsasDocument doc=null;
216 IdFactory vorba = null;
217 // TODO: reduce size of vorba ids generated from these parameters to IdFactory (mainly sessionHandle rationalization ?)
219 va.setVorba(vorba=makeVorbaIdFactory());
220 // if session currently holds data - read it in - or get a dummy
221 _session.slog.debug("Accessing document");
223 va.getVamsasDocument(user.getFullName()+" using "+client.getClientName(),
224 "created new session document.", null);
226 _session.slog.debug("Successfully retrieved document.");
228 log.error("Unexpectedly retrieved null document!");
230 catch (Exception e) {
231 log.error("Failed to get session document for session directory '"+_session.sessionDir+"'", e);
232 throw new IOException("Failed to get session document for session directory '"+_session.sessionDir+"'");
234 // Construct the IClientDocument instance
236 ClientDocument cdoc = new ClientDocument(doc, va, vorba, this);
243 * @see org.vamsas.client.IClient#updateDocument(org.vamsas.client.IClientDocument)
245 public void updateDocument(IClientDocument newdoc) {
246 if (!(newdoc instanceof ClientDocument)) {
247 throw new Error("Invalid IClientDocument instance for SimpleClient.");
250 // try to update the sessionFile
252 // write the appHandle to the lastupdate file.
259 * @see org.vamsas.client.IClient#storeDocument(java.io.File)
261 public void storeDocument(File location) {
263 // write storeDocument file to inform other clients that they should raise
264 Lock vamlock = evgen.want_to_store();
265 // Events.DOCUMENT_FINALIZEAPPDATA
267 _session.writeVamsasDocument(location, vamlock);
268 _session.clearUnsavedFlag();
269 } catch (Exception e) {
270 log.warn("Exception whilst trying to store document in "+location,e);
279 * @see org.vamsas.client.IClient#addVorbaEventHandler(java.lang.String,
280 * java.beans.PropertyChangeListener)
282 public void addVorbaEventHandler(String EventChain, PropertyChangeListener evt) {
283 if (handlers.containsKey(EventChain)) {
285 ((PropertyChangeSupport) (handler = handlers.get(EventChain)))
286 .addPropertyChangeListener(evt);
287 listeners.add(handler);
288 listeners.add((Object) evt);
293 * @see org.vamsas.client.IClient#pollUpdate()
295 public void pollUpdate() {
298 log.warn("pollUpdate called on incomplete SimpleClient object.");
302 if (!evgen.isAlive()) {
303 log.warn("pollUpdate called before joinSession()");
306 } catch (Exception e) {
307 log.error("Unexpected exception on default call to joinSession",e);
311 //TODO ensure event generator robustly handles these interrupts.
312 log.debug("interrrupting event generator.");
314 log.debug("interrrupted event generator.");
318 * @see org.vamsas.client.IClient#joinSession()
320 public void joinSession() throws Exception {
321 // start the EventGenerator thread.
323 log.warn("joinSession called on incomplete SimpleClient object.");
327 throw new Error("Join session called twice for the same SimpleClient (IClient instance).");
330 log.debug("Started EventGenerator thread.");
332 log.warn("Failed to start EventGenerator thread.");
333 throw new Exception("Failed to start event generator thread - client cannot be instantiated.");
335 if (evgen.countHandlersFor(Events.DOCUMENT_CREATE)>0) {
336 //TODO: is this application connecting to a newly created session document ?
337 //evgen.raise(Events.DOCUMENT_CREATE);
344 * @see org.vamsas.client.IClient#importDocument(java.io.File)
346 public void importDocument(File location) {
347 // TODO LATER: implement SimpleClient.importDocument()
348 log.error("importDocument is not implemented for a SimpleClient Session.");