1 package org.vamsas.client.simpleclient;
3 import org.vamsas.client.*;
5 import java.io.BufferedInputStream;
6 import java.io.BufferedOutputStream;
8 import java.io.FileInputStream;
9 import java.io.FileNotFoundException;
10 import java.io.FileOutputStream;
11 import java.io.IOException;
12 import java.io.InputStreamReader;
13 import java.io.ObjectInputStream;
14 import java.io.ObjectOutput;
15 import java.io.ObjectOutputStream;
16 import java.io.OutputStream;
17 import java.util.Vector;
20 * Handler for the clientsFile within a vamsas session thread.
23 public class ClientsFile {
24 private File filelist;
27 * number of my client in list (not known at start but used when known to make
30 private int syncnum = 1;
32 public ClientsFile(File filelist) throws IOException {
33 this.filelist = filelist;
34 if (!this.filelist.exists())
35 this.filelist.createNewFile();
38 private Lock listlock = null;
40 protected boolean lockList(Lock extantlock) {
41 if (listlock!=null && !listlock.isLocked()) {
42 listlock.release();// tidy up invalid lock
48 * Get a lock for the ClientsFile
50 * @return true if lock was made
52 protected boolean lockList() {
54 if (listlock.isLocked())
57 // lock failed for some reason.
60 if (filelist != null) {
61 if (filelist.exists()) {
62 // TODO: see if we need to loop-wait for locks or they just block until
67 listlock = new Lock(filelist); // TODO: wait around if we can't get the lock.
68 } while (!listlock.isLocked());
69 // listlock = new Lock(filelist);
70 return listlock.isLocked();
74 "org.vamsas.client.simpleclient.ClientsFile.lockList called for non-initialised ClientsFile!");
81 * Explicitly release the ClientsFile lock.
83 * @return true if lock was released.
85 protected void unlockList() {
86 if (listlock != null) {
93 * internal method for getting clientList - ensures a lock has been made but
94 * does not release it.
96 * @return list of clients
98 private ClientHandle[] retrieveClientHandles() {
101 ClientHandle[] clients=null;
102 if (this.listlock.rafile.length()>0) {
103 ObjectInputStream is = new ObjectInputStream(new BufferedInputStream(
104 new java.io.FileInputStream(filelist)));
109 clients = (ClientHandle[]) o;
111 catch (Exception e) {
112 System.err.println("Garbage in the clientHandle list "+this.filelist);
117 } catch (FileNotFoundException e) {
118 // TODO Auto-generated catch block
119 e.printStackTrace(System.err);
120 } catch (Exception e) {
121 e.printStackTrace(System.err);
127 * get the clientList from the file. May return null if lock failed!
130 public ClientHandle[] retrieveClientList() {
132 ClientHandle[] clients = retrieveClientHandles();
139 * get list from the locked ClientList.
141 * @return clientList or null if lock failed (or file was empty)
143 public ClientHandle[] retrieveClientList(Lock extantlock) {
144 if (lockList(extantlock)) {
145 ClientHandle[] clients = retrieveClientHandles();
152 * adds clientHandle me to the clientList under an existing lock extantLock.
155 * @return client index in list or 0 if lock was invalid or addClient operation failed.
157 public int addClient(ClientHandle me, Lock extantLock) {
158 return addClient(me, true, extantLock);
162 * adds clientHandle me to the clientList under an existing lock.
163 * @param me - clientHandle
164 * @param disambig - if true then add will fail if an identical clientHandle already exists
165 * @param extantLock - existing lock
166 * @return client index in list or 0 if addClient (or the lock) failed.
169 public int addClient(ClientHandle me, boolean disambig, Lock extantLock) {
170 if (lockList(extantLock)) {
171 syncnum = addClient(me, disambig);
179 * adds the ClientHandle to the list - if it is not unique, then the
180 * ClientHandle object is modified to make it unique in the list. returns the
181 * clientNumber for the client in the session.
187 public int addClient(ClientHandle me) {
188 syncnum = addClient(me, true);
194 * removes 'me' from the session ClientList without complaint if 'me' isn't in the clientList already.
195 * @param me client handle to be removed
196 * @param clientlock existing lock passed from watcher.
198 public void removeClient(ClientHandle me, Lock clientlock) {
200 if (lockList(clientlock)) {
201 ClientHandle[] clients = retrieveClientHandles();
202 if (clients != null) {
203 if ((syncnum<=0 || syncnum>clients.length) || clients[syncnum-1]!=me) {
204 for (int i = 0, j = clients.length; i < j; i++)
205 if (clients[i].equals(me)) {
213 ClientHandle[] newlist = new ClientHandle[clients.length - 1];
214 for (int k=0,i = 0, j = clients.length; i < j; i++)
216 newlist[k++] = clients[i];
217 if (!putClientList(newlist))
218 throw new Error("Failed to write new clientList!"); // failed to put the clientList to disk.
223 throw new Error("Couldn't get lock for "+((filelist==null) ? "Unitialised filelist in ClientsFile" : filelist.getAbsolutePath()));
227 * Adds a ClientHandle to the ClientList file - optionally disambiguating
228 * the ClientHandle (modifes the URN).
229 * Note: Caller is left to release the lock on the ClientList.
231 * @param disambiguate -
232 * flag indicating if the URN for me should be disambiguated to
233 * differentiate between sessions.
234 * @return index of clientHandle in new list, or -1-position of existing
235 * clientHandle (if disambiguate is true)
237 protected int addClient(ClientHandle me, boolean disambiguate) {
240 ClientHandle[] clients = retrieveClientHandles();
241 if (me.getClientUrn()==null) {
242 // TODO: move this into ClientUrn as a standard form method.
243 me.setClientUrn("vamsas://"+me.getClientName()+":"+me.getVersion()+"/");
245 if (clients == null) {
246 clients = new ClientHandle[1];
251 for (int i = 0, j = clients.length; i < j; i++) {
252 if (clients[i].equals(me)) {
254 while (clients[i].equals(me)) {
255 me.setClientUrn(me.getClientUrn() + k++); // TODO: make a better
260 // will not write the ambiguous clientHandle to disk, just return
267 ClientHandle[] newlist = new ClientHandle[clients.length + 1];
268 for (i = 0, j = clients.length; i < j; i++)
269 newlist[i] = clients[i];
274 if (!putClientList(clients))
275 return 0; // failed to put the clientList to disk.
281 * safely writes clients array to the file referred to by filelist.
284 * @return true if successful write. Throws Errors otherwise.
286 protected boolean putClientList(ClientHandle[] clients) {
288 File templist = null;
290 templist = File.createTempFile(filelist.getName(),".old", filelist.getParentFile());
291 FileOutputStream tos = new FileOutputStream(templist);
292 tos.getChannel().transferFrom(listlock.rafile.getChannel(), 0,
293 listlock.rafile.length());
295 } catch (FileNotFoundException e1) {
296 System.err.println("Can't create temp file for clientlist");
297 e1.printStackTrace(System.err);
298 } catch (IOException e1) {
300 .println("Error when copying content to temp file for clientlist");
301 e1.printStackTrace(System.err);
303 if (templist != null) {
305 listlock.rafile.setLength(0);
306 ObjectOutputStream os = new ObjectOutputStream(
307 new BufferedOutputStream(new FileOutputStream(this.filelist)));
308 os.writeObject(clients);
310 // All done - remove the backup.
313 } catch (Exception e) {
314 if (templist != null) {
316 .println("Serious - problems writing to filelist. Backup in "
317 + templist.getAbsolutePath());
318 e.printStackTrace(System.err);
323 "Couldn't create backup of the clientList before writing to it!");
326 throw new Error("Could not lock the clientList: "
327 + ((filelist == null) ? "Unitialized ClientsFile"
328 : " failed to get lock on " + filelist.getAbsolutePath()));