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 java.io.File;
\r
25 import java.io.FileNotFoundException;
\r
26 import java.io.FileOutputStream;
\r
27 import java.io.ObjectInputStream;
\r
28 import java.io.ObjectOutputStream;
\r
29 import java.net.URL;
\r
31 import org.apache.commons.logging.Log;
\r
32 import org.apache.commons.logging.LogFactory;
\r
34 import uk.ac.vamsas.client.SessionHandle;
\r
35 import uk.ac.vamsas.client.simpleclient.SimpleSessionHandle;
\r
38 * @author <a href="mailto:pierre@ebi.ac.uk">Pierre MARGUERITE</a>
\r
42 public class SessionsFile extends ListFile {
\r
44 private static Log log = LogFactory.getLog(SessionsFile.class);
\r
47 * when set true - get FileNotFoundExceptions on WinXP when writing to locked
\r
48 * stream after the backup has been made (via the backupFile method)
\r
50 boolean backup = false;
\r
53 * number of my session in list - passed back when a session is added to list,
\r
54 * and used (if valid) for quickly looking up presence of session handle in
\r
57 private int syncnum = 1;
\r
62 public SessionsFile(File file) throws java.io.IOException {
\r
67 * internal method for getting sessionsList - ensures a lock has been made but
\r
68 * does not release it.
\r
70 * @return list of clients
\r
72 private SimpleSessionHandle[] retrieveSessionHandles() {
\r
75 SimpleSessionHandle[] sessions = null;
\r
76 if (this.fileLock.length() > 0) {
\r
78 ObjectInputStream is = new ObjectInputStream(this.fileLock
\r
79 .getBufferedInputStream(true));
\r
81 o = is.readObject();
\r
84 if (o instanceof SimpleSessionHandle[]) {
\r
85 sessions = (SimpleSessionHandle[]) o;
\r
87 // legacy support or incorrect path.
\r
88 if (o instanceof SessionHandle[]) {
\r
89 log.info("Importing VAMSAS 0.1 clientHandle list.");
\r
90 SessionHandle[] oldsess = (SessionHandle[]) o;
\r
92 sessions = new SimpleSessionHandle[oldsess.length];
\r
93 for (int s=0;s<oldsess.length;s++)
\r
96 sessdir = new SessionUrn(oldsess[s].getSessionUrn()).asFile();
\r
97 // try to locate it.
\r
98 sessions[s] = new SimpleSessionHandle(oldsess[s].getSessionUrn(), sessdir);
\r
99 } catch (Exception e)
\r
101 // give up and report an error.
\r
103 throw new Exception("Legacy SessionFile problem. Couldn't locate "+oldsess[s]+" as a file.",e);
\r
108 } catch (Exception e) {
\r
109 log.error("Garbage in the clientHandle list " + this.sessionFile,
\r
116 } catch (FileNotFoundException e) {
\r
117 // e.printStackTrace(System.err);
\r
119 } catch (Exception e) {
\r
121 // e.printStackTrace(System.err);
\r
128 * get the SessionsList from the file. May return null if lock failed!
\r
130 * @return sessionsList
\r
132 public SimpleSessionHandle[] retrieveSessionsList() {
\r
134 SimpleSessionHandle[] clients = retrieveSessionHandles();
\r
142 * get list from the locked SessionsList.
\r
144 * @param extantlock
\r
145 * @return sessionList or null if lock failed (or file was empty)
\r
147 public SimpleSessionHandle[] retrieveSessionsList(Lock extantlock) {
\r
148 if (lockFile(extantlock)) {
\r
149 SimpleSessionHandle[] sessions = retrieveSessionHandles();
\r
157 * adds SessionHandle me to the sessionList under an existing lock extantLock.
\r
159 * @param newSession
\r
160 * @param extantLock
\r
161 * @return session index in list or 0 if lock was invalid or addSession
\r
162 * operation failed.
\r
164 public int addSession(SimpleSessionHandle newSession, Lock extantLock) {
\r
165 return addSession(newSession, true, extantLock);
\r
169 * adds SessionsHandle me to the sessionsList under an existing lock.
\r
171 * @param newSession
\r
174 * - if true then add will fail if an identical sessionHandle already
\r
176 * @param extantLock
\r
178 * @return client index in list or 0 if addSession (or the lock) failed.
\r
181 public int addSession(SimpleSessionHandle newSession, boolean disambig,
\r
183 if (lockFile(extantLock)) {
\r
184 this.syncnum = addSession(newSession, disambig);
\r
186 return this.syncnum;
\r
192 * removes the current session from the SessionsList without complaint if the
\r
193 * session isn't in the sessionsList already.
\r
196 * session handle to be removed
\r
197 * @param sessionlock
\r
198 * existing lock passed from watcher.
\r
200 public void removeSession(SessionHandle session, Lock sessionlock) {
\r
202 if (lockFile(sessionlock)) {
\r
204 SimpleSessionHandle[] sessions = retrieveSessionHandles();
\r
205 if (sessions != null) {
\r
206 if ((this.syncnum <= 0 || this.syncnum > sessions.length)
\r
207 || !session.equals(sessions[this.syncnum - 1])) {
\r
208 for (int i = 0, j = sessions.length; i < j; i++) {
\r
209 if (sessions[i].equals(session)) {
\r
215 mynum = this.syncnum - 1;
\r
219 SimpleSessionHandle[] newlist = new SimpleSessionHandle[sessions.length - 1];
\r
220 for (int k = 0, i = 0, j = sessions.length; i < j; i++)
\r
222 newlist[k++] = sessions[i];
\r
223 if (!putSessionsList(newlist))
\r
224 throw new Error("Failed to write new sessionsList!"); // failed to
\r
233 "Couldn't get lock for "
\r
234 + ((this.sessionFile == null) ? "Unitialised sessionFile in SessionsFile"
\r
235 : this.sessionFile.getAbsolutePath()));
\r
240 * Adds a SessionHandle to the SessionList file - optionally disambiguating
\r
241 * the SessionHandle (modifes the URN). Note: Caller is left to release the
\r
242 * lock on the SessionList.
\r
245 * @param disambiguate
\r
246 * - flag indicating if the URN for me should be disambiguated to
\r
247 * differentiate between sessions.
\r
248 * @return index of sessionHandle in new list, or -1-position of existing
\r
249 * sessionHandle (if disambiguate is true)
\r
251 protected int addSession(SimpleSessionHandle session, boolean disambiguate) {
\r
252 int newsession = 0;
\r
254 while (tries-- > 0 && !lockFile())
\r
257 } catch (Exception e) {
\r
261 SimpleSessionHandle[] sessions = retrieveSessionHandles();
\r
263 if (sessions == null) {
\r
264 sessions = new SimpleSessionHandle[1];
\r
265 sessions[0] = session;
\r
269 for (int i = 0, j = sessions.length; i < j; i++) {
\r
270 if (sessions[i].equals(session)) {
\r
271 if (disambiguate) {
\r
272 while (sessions[i].equals(session)) {
\r
273 // me.setClientUrn(me.getClientUrn() + k++); // TODO: make a
\r
275 // disambiguation of
\r
279 // will not write the ambiguous clientHandle to disk, just return
\r
286 SimpleSessionHandle[] newlist = new SimpleSessionHandle[sessions.length + 1];
\r
287 for (i = 0, j = sessions.length; i < j; i++)
\r
288 newlist[i] = sessions[i];
\r
289 newlist[j] = session;
\r
290 sessions = newlist;
\r
291 newsession = j + 1;
\r
293 if (!putSessionsList(sessions))
\r
294 return 0; // failed to put the clientList to disk.
\r
300 * safely writes sessions array to the file referred to by sessionFile.
\r
303 * @return true if successful write. Throws Errors otherwise.
\r
305 protected boolean putSessionsList(SimpleSessionHandle[] clients) {
\r
307 File templist = null;
\r
308 if (!this.backup || (templist = backupSessionFile()) != null) {
\r
310 while (retries-- > 0) {
\r
312 ObjectOutputStream os = new ObjectOutputStream(this.fileLock
\r
313 .getBufferedOutputStream(true));
\r
314 log.debug("About to write " + clients.length
\r
315 + " sessionHandles to output stream.");
\r
316 os.writeObject(clients);
\r
319 // All done - remove the backup.
\r
324 } catch (Exception e) {
\r
326 // .println("Serious - problems writing to sessionFile.");
\r
327 log.error("Serious - problems writing to sessionFile.", e);
\r
328 if (retries > 0 && templist != null) {
\r
329 // System.err.println("Recovering from Backup in "
\r
330 // + templist.getAbsolutePath());
\r
331 log.error("Recovering from Backup in "
\r
332 + templist.getAbsolutePath());
\r
333 templist.renameTo(this.fileLock.target);
\r
335 // e.printStackTrace(System.err);
\r
339 if (retries > -2) {
\r
341 // .println("Serious - problems writing to sessionFile. Giving Up.");
\r
342 log.error("Serious - problems writing to sessionFile. Giving Up.");
\r
347 "Couldn't create backup of the clientList before writing to it!");
\r
350 throw new Error("Could not lock the clientList: "
\r
351 + ((this.sessionFile == null) ? "Unitialized ClientsFile"
\r
352 : " failed to get lock on " + this.sessionFile.getAbsolutePath()));
\r
358 public void clearList() {
\r
361 FileOutputStream fout = this.fileLock.getFileOutputStream(true);
\r
364 } catch (Exception e) {
\r
365 throw new Error("Problems trying to clear clientlist!", e);
\r