2 * This file is part of the Vamsas Client version 0.2.
\r
3 * Copyright 2010 by Jim Procter, Iain Milne, Pierre Marguerite,
\r
4 * Andrew Waterhouse and Dominik Lindner.
\r
6 * Earlier versions have also been incorporated into Jalview version 2.4
\r
7 * since 2008, and TOPALi version 2 since 2007.
\r
9 * The Vamsas Client is free software: you can redistribute it and/or modify
\r
10 * it under the terms of the GNU Lesser General Public License as published by
\r
11 * the Free Software Foundation, either version 3 of the License, or
\r
12 * (at your option) any later version.
\r
14 * The Vamsas Client is distributed in the hope that it will be useful,
\r
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
17 * GNU Lesser General Public License for more details.
\r
19 * You should have received a copy of the GNU Lesser General Public License
\r
20 * along with the Vamsas Client. If not, see <http://www.gnu.org/licenses/>.
\r
22 package uk.ac.vamsas.client.simpleclient;
\r
24 import uk.ac.vamsas.client.*;
\r
26 import java.io.BufferedInputStream;
\r
27 import java.io.BufferedOutputStream;
\r
28 import java.io.File;
\r
29 import java.io.FileInputStream;
\r
30 import java.io.FileNotFoundException;
\r
31 import java.io.FileOutputStream;
\r
32 import java.io.IOException;
\r
33 import java.io.InputStreamReader;
\r
34 import java.io.ObjectInputStream;
\r
35 import java.io.ObjectOutput;
\r
36 import java.io.ObjectOutputStream;
\r
37 import java.io.OutputStream;
\r
38 import java.util.Vector;
\r
41 * Handler for the clientsFile within a vamsas session thread.
\r
45 public class ClientsFile extends ListFile {
\r
46 private static org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory
\r
47 .getLog(ClientsFile.class);
\r
50 * number of my client in list - passed back when a client is added to list,
\r
51 * and used (if valid) for quickly looking up presence of client handle in the
\r
54 private int syncnum = 1;
\r
56 public ClientsFile(File filelist) throws IOException {
\r
61 * internal method for getting clientList - ensures a lock has been made but
\r
62 * does not release it.
\r
64 * @return list of clients
\r
66 private ClientHandle[] retrieveClientHandles() {
\r
69 ClientHandle[] clients = null;
\r
70 if (fileLock.length() > 0) {
\r
72 ObjectInputStream is = new ObjectInputStream(fileLock
\r
73 .getBufferedInputStream(true));
\r
75 o = is.readObject();
\r
78 clients = (ClientHandle[]) o;
\r
79 } catch (Exception e) {
\r
80 System.err.println("Garbage in the clientHandle list "
\r
81 + this.sessionFile);
\r
86 } catch (FileNotFoundException e) {
\r
87 // TODO Auto-generated catch block
\r
88 e.printStackTrace(System.err);
\r
89 } catch (Exception e) {
\r
90 e.printStackTrace(System.err);
\r
97 * get the clientList from the file. May return null if lock failed!
\r
99 * @return clientList
\r
101 public ClientHandle[] retrieveClientList() {
\r
103 ClientHandle[] clients = retrieveClientHandles();
\r
111 * get list from the locked ClientList.
\r
113 * @param extantlock
\r
114 * @return clientList or null if lock failed (or file was empty)
\r
116 public ClientHandle[] retrieveClientList(Lock extantlock) {
\r
117 if (lockFile(extantlock)) {
\r
118 ClientHandle[] clients = retrieveClientHandles();
\r
126 * adds clientHandle me to the clientList under an existing lock extantLock.
\r
129 * @param extantLock
\r
130 * @return client index in list or 0 if lock was invalid or addClient
\r
131 * operation failed.
\r
133 public int addClient(ClientHandle me, Lock extantLock) {
\r
134 return addClient(me, true, extantLock);
\r
138 * adds clientHandle me to the clientList under an existing lock.
\r
143 * - if true then add will fail if an identical clientHandle already
\r
145 * @param extantLock
\r
147 * @return client index in list or 0 if addClient (or the lock) failed.
\r
150 public int addClient(ClientHandle me, boolean disambig, Lock extantLock) {
\r
151 if (lockFile(extantLock)) {
\r
152 syncnum = addClient(me, disambig);
\r
160 * adds the ClientHandle to the list - if it is not unique, then the
\r
161 * ClientHandle object is modified to make it unique in the list. returns the
\r
162 * clientNumber for the client in the session.
\r
168 public int addClient(ClientHandle me) {
\r
169 syncnum = addClient(me, true);
\r
175 * removes 'me' from the session ClientList without complaint if 'me' isn't in
\r
176 * the clientList already.
\r
179 * client handle to be removed
\r
180 * @param clientlock
\r
181 * existing lock passed from watcher.
\r
183 public void removeClient(ClientHandle me, Lock clientlock) {
\r
185 if (lockFile(clientlock)) {
\r
186 ClientHandle[] clients = retrieveClientHandles();
\r
187 if (clients != null) {
\r
188 if ((syncnum <= 0 || syncnum > clients.length)
\r
189 || clients[syncnum - 1] != me) {
\r
190 for (int i = 0, j = clients.length; i < j; i++)
\r
191 if (clients[i].equals(me)) {
\r
196 mynum = syncnum - 1;
\r
199 ClientHandle[] newlist = new ClientHandle[clients.length - 1];
\r
200 for (int k = 0, i = 0, j = clients.length; i < j; i++)
\r
202 newlist[k++] = clients[i];
\r
203 if (!putClientList(newlist))
\r
204 throw new Error("Failed to write new clientList!"); // failed to put
\r
212 throw new Error("Couldn't get lock for "
\r
213 + ((sessionFile == null) ? "Unitialised sessionFile in ClientsFile"
\r
214 : sessionFile.getAbsolutePath()));
\r
219 * Adds a ClientHandle to the ClientList file - optionally disambiguating the
\r
220 * ClientHandle (modifes the URN). Note: Caller is left to release the lock on
\r
224 * @param disambiguate
\r
225 * - flag indicating if the URN for me should be disambiguated to
\r
226 * differentiate between sessions.
\r
227 * @return index of clientHandle in new list, or -1-position of existing
\r
228 * clientHandle (if disambiguate is true)
\r
230 protected int addClient(ClientHandle me, boolean disambiguate) {
\r
233 while (tries-- > 0 && !lockFile())
\r
236 } catch (Exception e) {
\r
240 ClientHandle[] clients = retrieveClientHandles();
\r
241 if (me.getClientUrn() == null) {
\r
242 // TODO: move this into ClientUrn as a standard form method.
\r
243 me.setClientUrn("vamsas://" + me.getClientName() + ":"
\r
244 + me.getVersion() + "/");
\r
246 if (clients == null) {
\r
247 clients = new ClientHandle[1];
\r
252 for (int i = 0, j = clients.length; i < j; i++) {
\r
253 if (clients[i].equals(me)) {
\r
254 if (disambiguate) {
\r
255 while (clients[i].equals(me)) {
\r
256 me.setClientUrn(me.getClientUrn() + k++); // TODO: make a better
\r
257 // disambiguation of
\r
261 // will not write the ambiguous clientHandle to disk, just return
\r
268 ClientHandle[] newlist = new ClientHandle[clients.length + 1];
\r
269 for (i = 0, j = clients.length; i < j; i++)
\r
270 newlist[i] = clients[i];
\r
275 if (!putClientList(clients))
\r
276 return 0; // failed to put the clientList to disk.
\r
282 * when set true - get FileNotFoundExceptions on WinXP when writing to locked
\r
283 * stream after the backup has been made (via the backupFile method)
\r
285 boolean backup = false;
\r
288 * safely writes clients array to the file referred to by sessionFile.
\r
291 * @return true if successful write. Throws Errors otherwise.
\r
293 protected boolean putClientList(ClientHandle[] clients) {
\r
295 File templist = null;
\r
297 templist = backupSessionFile();
\r
299 if (!backup || (templist != null)) {
\r
301 while (retries-- > 0) {
\r
303 ObjectOutputStream os = new ObjectOutputStream(fileLock
\r
304 .getBufferedOutputStream(true));
\r
305 log.debug("About to write " + clients.length
\r
306 + " clientHandles to output stream.");
\r
307 os.writeObject(clients);
\r
309 // All done - remove the backup.
\r
314 } catch (Exception e) {
\r
315 System.err.println("Serious - problems writing to sessionFile.");
\r
316 if (retries > 0 && templist != null) {
\r
317 System.err.println("Recovering from Backup in "
\r
318 + templist.getAbsolutePath());
\r
319 templist.renameTo(fileLock.target);
\r
321 e.printStackTrace(System.err);
\r
324 if (retries > -2) {
\r
326 .println("Serious - problems writing to sessionFile. Giving Up.");
\r
331 "Couldn't create backup of the clientList before writing to it!");
\r
334 throw new Error("Could not lock the clientList: "
\r
335 + ((sessionFile == null) ? "Unitialized ClientsFile"
\r
336 : " failed to get lock on " + sessionFile.getAbsolutePath()));
\r
342 public void clearList() {
\r
345 FileOutputStream fout = fileLock.getFileOutputStream(true);
\r
348 } catch (Exception e) {
\r
349 throw new Error("Problems trying to clear clientlist!", e);
\r