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