f0b2e16d02105d7e980b731c68bcf16058428d9a
[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         doclock = 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     valid();
179     try {
180       // patiently wait for a lock on the document.
181       long tries=5000;
182       org.vamsas.client.simpleclient.Lock lock;
183       while (((lock=vsess.getLock())==null || !lock.isLocked()) && --tries>0) {
184 //        Thread.sleep(1);
185         log.debug("Trying to get a document lock for the "+tries+"'th time.");
186       }
187       VamsasArchive varc = new VamsasArchive(vsess, true, false); // read archive, write as vamsasDocument, don't erase original contents.
188       varc.setVorba(this);
189       VamsasDocument d = varc.getVamsasDocument(getProvenanceUser(), "Created new document.", VersionEntries.latestVersion()); // VAMSAS: provenance user and client combined
190       
191       if (d==null) {
192         log.warn("Backing out from opening a VamsasArchive writable IO session");
193         varc.cancelArchive();
194         return null;
195       }      
196       ClientDoc cdoc = new ClientDoc(d, varc, varc.getOriginalArchiveReader(), getClientHandle().getClientUrn(), getProvenanceUser(), getVorbaIdHash());
197       return cdoc;
198       // do appHandle?
199     } catch (Exception e) {
200       log.error("Failed to get Updateable version of "+vsess.getVamsasFile(), e);
201     }
202     return null;
203   }
204   /**
205    * trust client to not do anything stupid to the document roots which will now be written to the archive.
206    * @param cdoc
207    * @return true if write was a success.
208    */
209   public boolean doUpdate(ClientDoc cdoc) {
210     valid();
211     if (cdoc==null) {
212       log.warn("Invalid ClientDoc passed to org.vamsas.test.simpleclient.doUpdate()");
213       return false;
214     }
215     if (cdoc.iohandler==null) {
216       log.warn("Read only ClientDoc object passed to org.vamsas.test.simpleclient.doUpdate()");
217       return false;
218     }
219     if (cdoc.iohandler.getVorba()!=this) {
220       log.error("Mismatch between ClientDoc instances and ArchiveClient instances!");
221       return false;
222     }
223     try {
224       // do any appDatas first.
225       if (cdoc.iohandler.transferRemainingAppDatas())
226         log.debug("Remaining appdatas were transfered.");
227       cdoc.updateDocumentRoots();
228       cdoc.iohandler.putVamsasDocument(cdoc.doc);
229       cdoc.iohandler.closeArchive();
230       cdoc.iohandler=null;
231       cdoc = null;
232       vsess.unLock();
233     } catch (Exception e) {
234       log.warn("While updating archive in "+vsess.getVamsasFile(),e);
235       return false;
236     }
237     return true;
238   }
239   /**
240    * @param args
241    */
242   public static void usage() {
243     throw new Error("Usage: Username Organization VamsasFile [command,args]*");
244   }
245   public static void main(String[] args) {
246     // really simple.
247     if (args.length<3)
248       usage();
249     
250     ArchiveClient client = new ArchiveClient(args[0],args[1], new File(args[2]));
251     ClientDoc cdoc=null;
252     // sanity test.
253     try {
254       cdoc = client.getUpdateable();
255       // ArchiveReports.reportDocument(cdoc.doc, cdoc.getReader(), true, System.out);
256       System.out.println("Report Roots :");
257       ArchiveReports.rootReport(cdoc.getVamsasRoots(), true, System.out);
258       cdoc.addVamsasRoot(Core.getDemoVamsas());
259       System.out.println("Doing update.");
260       client.doUpdate(cdoc);
261       cdoc.closeDoc();
262       cdoc = null;
263       int u=5;
264       while (--u>0) {
265         System.out.println("Watch for more... ("+u+" left)");
266         ClientDoc ucdoc = client.watch(50000);
267         if (ucdoc!=null) {
268           System.out.println("****\nUpdate detected at "+new Date());
269           ArchiveReports.reportDocument(ucdoc.doc, ucdoc.getReader(), true, System.out);
270           ucdoc.closeDoc();
271           ucdoc=null;
272         } else {
273           System.out.println("!!!! Null document update detected at "+new Date());
274         }
275       }
276     }
277     catch (Exception e) {
278       client.log.error("Broken!", e);
279     }
280     System.out.println("Finished at "+new Date());
281   }
282   public org.vamsas.client.Vobject getObject(VorbaId id) {
283     Hashtable idhash = this.getVorbaIdHash();
284     if (idhash!=null && idhash.containsKey(id))
285       return (Vobject) idhash.get(id);
286     return null;
287     }
288 }