ensured that hash binding vorbaIds is passed to client document object for vorba...
[vamsas.git] / src / org / vamsas / test / simpleclient / ArchiveClient.java
1 /**
2  * 
3  */
4 package org.vamsas.test.simpleclient;
5
6 import java.io.File;
7 import java.io.IOException;
8 import java.util.Date;
9 import java.util.Hashtable;
10 import java.util.Vector;
11
12 import org.apache.commons.logging.Log;
13 import org.apache.commons.logging.LogFactory;
14 import org.exolab.castor.xml.MarshalException;
15 import org.exolab.castor.xml.ValidationException;
16 import org.vamsas.client.ClientHandle;
17 import org.vamsas.client.IVorbaIdFactory;
18 import org.vamsas.client.SessionHandle;
19 import org.vamsas.client.UserHandle;
20 import org.vamsas.client.Vobject;
21 import org.vamsas.client.VorbaId;
22 import org.vamsas.client.simpleclient.AppDataOutputStream;
23 import org.vamsas.client.simpleclient.FileWatcher;
24 import org.vamsas.client.simpleclient.IdFactory;
25 import org.vamsas.client.simpleclient.SessionFile;
26 import org.vamsas.client.simpleclient.SimpleDocBinding;
27 import org.vamsas.client.simpleclient.SimpleDocument;
28 import org.vamsas.client.simpleclient.VamsasArchive;
29 import org.vamsas.client.simpleclient.VamsasArchiveReader;
30 import org.vamsas.client.simpleclient.VamsasFile;
31 import org.vamsas.objects.core.AppData;
32 import org.vamsas.objects.core.ApplicationData;
33 import org.vamsas.objects.core.User;
34 import org.vamsas.objects.core.VamsasDocument;
35 import org.vamsas.objects.utils.AppDataReference;
36 import org.vamsas.objects.utils.DocumentStuff;
37 import org.vamsas.objects.utils.ProvenanceStuff;
38 import org.vamsas.objects.utils.SeqSet;
39 import org.vamsas.objects.utils.document.VersionEntries;
40 import org.vamsas.test.objects.Core;
41
42 /**
43  * @author jimp
44  *  test the VamsasFile routines for watching, reading and updating a vamsas document jar file.
45  *  simple document access base class.
46  */
47 public class ArchiveClient extends IdFactory {
48   
49   private Log log = LogFactory.getLog(ArchiveClient.class);
50   // protected UserHandle user=null;
51   // protected ClientHandle me = new ClientHandle("ArchiveClient","0.01");
52   VamsasFile vsess;
53   
54   /**
55    * @param user
56    * @param vsess
57    */
58   public ArchiveClient(UserHandle user, VamsasFile vsess) {
59     super(new SessionHandle("vamsasfile://"+vsess.getVamsasFile()), new ClientHandle("ArchiveClient","0.01"), user);
60     this.vsess = vsess;
61     valid();
62   }
63   private void _openVsess(File vsess) {
64     try {
65       this.vsess = new VamsasFile(vsess);
66     }
67     catch (Exception e) {
68       log.error("Couldn't open session for file "+vsess,e);
69       this.vsess = null;
70     }
71   }
72   public ArchiveClient(String username, String organization, File vsess) {
73     super(new SessionHandle("vamsasfile://"+vsess), new ClientHandle("ArchiveClient","0.01"), new UserHandle(username, organization));
74     _openVsess(vsess);
75     valid();
76   }
77   public ArchiveClient(String username, String organization, String clientName, String clientVersion, File vsess) {
78     super(new SessionHandle("vamsasfile://"+vsess), new ClientHandle(clientName, clientVersion), new UserHandle(username, organization));
79     _openVsess(vsess);
80     valid();
81   }
82   public void valid() {
83     if (vsess==null)
84       throw new Error("ArchiveClient instance is invalid!.");
85   }
86   /**
87    * set this to false if watch loop should end immediately
88    */
89   protected boolean watchForChange=true;
90   public static int WATCH_SLEEP=300;
91   /**
92    * watch the document file for updates.
93    * @param time - length of time to watch for.
94    * @return read only IO interface for session document.
95    */
96   public ClientDoc watch(long time) {
97     valid();
98     vsess.unLock(); // doh.
99     FileWatcher watcher = new FileWatcher(vsess.getVamsasFile());
100     // watcher.setState();
101     watchForChange=true;
102     long endtime=System.currentTimeMillis()+time;
103     try {
104       org.vamsas.client.simpleclient.Lock doclock;
105       do {
106         doclock=watcher.getChangedState();
107         if (doclock==null)
108           Thread.sleep(WATCH_SLEEP);
109       } while (watchForChange && doclock==null && (time==0 || endtime>System.currentTimeMillis())); // tuning.
110       if (doclock==null)
111         return null;
112       else {
113         return getUpdateable(vsess.getLock(doclock));
114         /*VamsasArchiveReader varc = new VamsasArchiveReader(vsess.getVamsasFile());
115         return _getReadonly(varc);*/
116       }
117     } catch (Exception e) {
118       log.error("Whilst watching file "+vsess.getVamsasFile(), e);
119     }
120     return null;
121   }
122
123   // from ClientDocument.getClientAppdata
124   private AppData[] getAppData(VamsasDocument doc) {
125     if (doc==null) {
126       log.debug("extractAppData called for null document object");
127       return null;
128     }
129     AppData appsGlobal=null, usersData=null;
130     Vector apldataset = AppDataReference.getUserandApplicationsData(
131         doc, this.getUserHandle(), this.getClientHandle());
132     if (apldataset!=null) {
133       if (apldataset.size()>0) {
134         AppData clientdat = (AppData) apldataset.get(0);
135         if (clientdat instanceof ApplicationData) {
136           appsGlobal = (ApplicationData) clientdat;
137           if (apldataset.size()>1) {
138             clientdat = (AppData) apldataset.get(1);
139             if (clientdat instanceof User) {
140               usersData = (User) clientdat;
141             }
142             if (apldataset.size()>2)
143               log.info("Ignoring additional ("+(apldataset.size()-2)+") AppDatas returned by document appdata query.");
144           } 
145         } else {
146           log.warn("Unexpected entry in AppDataReference query: id="+clientdat.getVorbaId()+" type="+clientdat.getClass().getName());
147         }
148         apldataset.removeAllElements(); // destroy references.
149       }
150     }
151     return new AppData[] { appsGlobal, usersData};
152   }
153   
154   protected ClientDoc _getReadonly(VamsasArchiveReader vreader) throws IOException, ValidationException, MarshalException {
155     valid();
156     if (vreader!=null) {
157       SimpleDocBinding docb = new SimpleDocBinding();
158       docb.setVorba(this);
159       VamsasDocument d;
160       d = docb.getVamsasDocument(vreader);
161       
162       if (d!=null) {
163         ClientDoc creader = new ClientDoc(d, null, vreader, getClientHandle().getClientUrn(), getProvenanceUser(), getVorbaIdHash());
164         return creader;
165       }
166     }
167     return null;
168   }  
169   /**
170    * from SimpleClient
171    * @return user field for a provenance entry
172    */
173   protected String getProvenanceUser() {
174     return new String(getUserHandle().getFullName()+" ["+getClientHandle().getClientUrn()+"]");
175   }
176   
177   public ClientDoc getUpdateable() {
178     return getUpdateable(null);
179   }
180   public ClientDoc getUpdateable(org.vamsas.client.simpleclient.Lock lock) {
181     getVorbaIdHash().clear();
182     valid();
183     try {
184       // patiently wait for a lock on the document.
185       long tries=5000;
186       while (lock==null && ((lock=vsess.getLock())==null || !lock.isLocked()) && --tries>0) {
187 //        Thread.sleep(1);
188         log.debug("Trying to get a document lock for the "+tries+"'th time.");
189       }
190       VamsasArchive varc = new VamsasArchive(vsess, true, false); // read archive, write as vamsasDocument, don't erase original contents.
191       varc.setVorba(this);
192       VamsasDocument d = varc.getVamsasDocument(getProvenanceUser(), "Created new document.", VersionEntries.latestVersion()); // VAMSAS: provenance user and client combined
193       
194       if (d==null) {
195         log.warn("Backing out from opening a VamsasArchive writable IO session");
196         varc.cancelArchive();
197         return null;
198       }      
199       ClientDoc cdoc = new ClientDoc(d, varc, varc.getOriginalArchiveReader(), getClientHandle().getClientUrn(), getProvenanceUser(), getVorbaIdHash());
200       return cdoc;
201       // do appHandle?
202     } catch (Exception e) {
203       log.error("Failed to get Updateable version of "+vsess.getVamsasFile(), e);
204     }
205     return null;
206   }
207   /**
208    * trust client to not do anything stupid to the document roots which will now be written to the archive.
209    * @param cdoc
210    * @return true if write was a success.
211    */
212   public boolean doUpdate(ClientDoc cdoc) {
213     valid();
214     if (cdoc==null) {
215       log.warn("Invalid ClientDoc passed to org.vamsas.test.simpleclient.doUpdate()");
216       return false;
217     }
218     if (cdoc.iohandler==null) {
219       log.warn("Read only ClientDoc object passed to org.vamsas.test.simpleclient.doUpdate()");
220       return false;
221     }
222     if (cdoc.iohandler.getVorba()!=this) {
223       log.error("Mismatch between ClientDoc instances and ArchiveClient instances!");
224       return false;
225     }
226     try {
227       // do any appDatas first.
228       if (cdoc.iohandler.transferRemainingAppDatas())
229         log.debug("Remaining appdatas were transfered.");
230       cdoc.updateDocumentRoots();
231       cdoc.iohandler.putVamsasDocument(cdoc.doc);
232       cdoc.iohandler.closeArchive();
233       this.extantids.clear();// we forget our ids after we close the document.
234       cdoc.iohandler=null;
235       cdoc = null;
236       vsess.unLock();
237     } catch (Exception e) {
238       log.warn("While updating archive in "+vsess.getVamsasFile(),e);
239       return false;
240     }
241     return true;
242   }
243   /**
244    * @param args
245    */
246   public static void usage() {
247     throw new Error("Usage: Username Organization VamsasFile [command,args]*");
248   }
249   public static void main(String[] args) {
250     // really simple.
251     if (args.length<3)
252       usage();
253     
254     ArchiveClient client = new ArchiveClient(args[0],args[1], new File(args[2]));
255     ClientDoc cdoc=null;
256     // sanity test.
257     try {
258       cdoc = client.getUpdateable();
259       // ArchiveReports.reportDocument(cdoc.doc, cdoc.getReader(), true, System.out);
260       System.out.println("Report Roots :");
261       ArchiveReports.rootReport(cdoc.getVamsasRoots(), true, System.out);
262       cdoc.addVamsasRoot(Core.getDemoVamsas());
263       System.out.println("Doing update.");
264       client.doUpdate(cdoc);
265       cdoc.closeDoc();
266       cdoc = null;
267       int u=5;
268       while (--u>0) {
269         System.out.println("Watch for more... ("+u+" left)");
270         ClientDoc ucdoc = client.watch(0000);
271         if (ucdoc!=null) {
272           System.out.println("****\nUpdate detected at "+new Date());
273           ArchiveReports.reportDocument(ucdoc.doc, ucdoc.getReader(), true, System.out);
274           ucdoc.closeDoc();
275           ucdoc=null;
276         } else {
277           System.out.println("!!!! Null document update detected at "+new Date());
278         }
279       }
280     }
281     catch (Exception e) {
282       client.log.error("Broken!", e);
283     }
284     System.out.println("Finished at "+new Date());
285   }
286   public org.vamsas.client.Vobject getObject(VorbaId id) {
287     Hashtable idhash = this.getVorbaIdHash();
288     if (idhash!=null && idhash.containsKey(id))
289       return (Vobject) idhash.get(id);
290     return null;
291     }
292 }