2 * This file is part of the Vamsas Client version 0.1.
3 * Copyright 2009 by Jim Procter, Iain Milne, Pierre Marguerite,
4 * Andrew Waterhouse and Dominik Lindner.
6 * Earlier versions have also been incorporated into Jalview version 2.4
7 * since 2008, and TOPALi version 2 since 2007.
9 * The Vamsas Client is free software: you can redistribute it and/or modify
10 * it under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation, either version 3 of the License, or
12 * (at your option) any later version.
14 * The Vamsas Client is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with the Vamsas Client. If not, see <http://www.gnu.org/licenses/>.
22 package uk.ac.vamsas.client.simpleclient;
26 import java.io.IOException;
27 import java.net.MalformedURLException;
29 import org.apache.commons.logging.Log;
30 import org.apache.commons.logging.LogFactory;
32 import uk.ac.vamsas.client.ClientHandle;
33 import uk.ac.vamsas.client.IClient;
34 import uk.ac.vamsas.client.IClientFactory;
35 import uk.ac.vamsas.client.InvalidSessionDocumentException;
36 import uk.ac.vamsas.client.InvalidSessionUrnException;
37 import uk.ac.vamsas.client.NoDefaultSessionException;
38 import uk.ac.vamsas.client.SessionHandle;
39 import uk.ac.vamsas.client.UserHandle;
43 * creates a session arena in the user home directory under .vamsas. Each
44 * session has its own subdirectory.
46 public class SimpleClientFactory implements IClientFactory {
48 private static Log log = LogFactory.getLog(SimpleClientFactory.class);
50 private File sessionArena = null;
52 private String vamsasSubdirectoryName = ".vamsas";
54 private SimpleSessionManager sessionManager = null;
56 private static final String SESSION_LIST = "sessions.obj";
58 // private String[] currentlyAvailableDessions = null;
61 * default constructor - called by CreateClientFactory only.
63 * Inits the sessionarena to the directory .vamsas of the user home directory.
66 public SimpleClientFactory() throws IOException {
69 // retrieves user home directory
70 String userHomeDirectory = System.getProperty("user.home");
71 if (userHomeDirectory == null || userHomeDirectory.length() < 1) {
72 new IOException("Unable to detect user home directory");
74 String sessionArenaPath = userHomeDirectory.concat(File.separator
75 .concat(this.vamsasSubdirectoryName));
77 this.initSessionArena(sessionArenaPath);
78 // this.initFactoryObjects();
82 * Create a client factory that works with sessions at the given path.
85 * path to directory called session arena, where will be created
86 * session directories and session files.
88 public SimpleClientFactory(String path) throws IOException {
89 this.initSessionArena(path);
93 * Inits sessionArena to a given path. checks if path is valid.
96 * path to a directory to use
98 * if the path is incorrect
100 private void initSessionArena(String path) throws IOException {
101 // Check path is valid and read/writeable.
102 File arenaFile = new File(path);
103 if (!arenaFile.exists()) {
104 if (!arenaFile.mkdirs()) {
105 this.sessionArena = null;
106 throw (new IOException("Unable to create a directory called " + path));
109 if (arenaFile.exists() && arenaFile.isDirectory() && arenaFile.canRead()
110 && arenaFile.canWrite()) {
111 this.sessionArena = arenaFile;
113 this.sessionArena = null;
114 throw (new IOException("Cannot read and write to a directory called "
120 * @see uk.ac.vamsas.client.IClientFactory#getIClient(uk.ac.vamsas.client.ClientHandle)
122 * Creates a IClient object, using default UserHandle with system
123 * variables:"user.name" or "USERNAME")), "host.name" or "HOSTNAME"
125 public IClient getIClient(ClientHandle applicationHandle)
126 throws NoDefaultSessionException {
127 // create a new session
128 // register new ClientHandle in session
129 // create SimpleClient instance
130 return this.getIClient(applicationHandle, (UserHandle) null);
134 * the URN should be something like simpleclient:FILEPATH URL encoded
136 * @see uk.ac.vamsas.client.IClientFactory#getIClient(uk.ac.vamsas.client.ClientHandle,
139 public IClient getIClient(ClientHandle applicationHandle, String sessionUrn) {
140 // locate session from Urn
141 // check that clientHandle is unique (with default user) - if not update the
142 // clientHandle urn to make it unique.
143 // wait for lock and attach to session
144 // create SimpleClient instance
145 log.debug("Trying to create session with URN " + sessionUrn);
146 return this.getIClient(applicationHandle, null, sessionUrn);
151 * try to locate the sessionUrn within the simpleclient session arena
154 * @throws InvalidSessionUrnException
156 private File convertSessionUrnToFile(String sessionUrn)
157 throws InvalidSessionUrnException {
158 if (sessionUrn == null) {
159 log.debug("Incorrect URN: can not open session.");
160 throw new InvalidSessionUrnException("SessionUrn was null");
163 SessionUrn urn = new SessionUrn(sessionUrn);
164 SimpleSessionHandle[] sh = null;
166 sh = getSessionManager().getSessionFor(urn);
167 } catch (IOException e)
169 log.warn("Ignored IO Exception when trying to access sessionlist.",e);
176 sesfile = new File(sh[0].getPhysLoc());
179 log.error("Raising exception for multiple session files corresponding to single URN (was : "+sessionUrn+")");
180 throw new InvalidSessionUrnException("IMPLEMENTATION ERROR: Multiple session files available for URN ("+sessionUrn+")");
188 * @see uk.ac.vamsas.client.IClientFactory#getIClient(uk.ac.vamsas.client.ClientHandle,
189 * uk.ac.vamsas.client.UserHandle, java.lang.String)
191 public IClient getIClient(ClientHandle applicationHandle, UserHandle userId,
193 // locate session from Urn
194 // check Uniqueness of user + ClientHandle in the session. Update
195 // clientHandle urn accordingly.
196 // wait for lock, attach to session
197 // create client instance
198 IClient client = null;
200 // TODO: implement 'opening stored session' opening mechanism
201 // 1. existing session document URL is vdoc://... ?
202 // 2. check for sessionUrn being of this form.
203 // 3. if it is - locate the file and pass to new VamsasSession
206 File sessionDirectory = convertSessionUrnToFile(sessionUrn);
209 .debug("found session directory "
210 + sessionDirectory.getAbsolutePath());
211 VamsasSession vamsasSession = new VamsasSession(sessionDirectory);
214 * if (userId == null) { //create a default userHandle //with current OS
215 * user and hostname userId = new
216 * UserHandle(System.getProperty("user.name",
217 * System.getProperty("USERNAME","Joe Doe")),
218 * System.getProperty("host.name",System.getProperty("HOSTNAME",
219 * "Unknown") ));// clientName, clientVersion, sessionPath); }
222 * //create simple client client = new SimpleClient(userId,
223 * applicationHandle, vamsasSession);
225 client = this.initClient(sessionDirectory, userId, applicationHandle,
227 } catch (MalformedURLException e) {
228 log.error("error while creating new IClient: incorrect session urn", e);
230 } catch (InvalidSessionDocumentException e) {
232 .error("error while creating new IClient: invalid session document",
235 } catch (InvalidSessionUrnException e) {
236 log.error("error while creating new IClient: incorrect session urn", e);
238 } catch (IOException e) {
239 log.error("error while creating new IClient: file access error", e);
246 * initialise the vamsas session state and create a SimpleClient object to
250 * newly created or existing session directory
252 * @param clientHandle
253 * @param vamsasDocument
254 * null or a document to pass to SimpleCLient to write into the
257 * @throws IOException
258 * if there are problems in session or client creation or if the
259 * session already has a vamsasDocument
260 * @throws InvalidSessionUrnException
261 * for a malformed sessdir
263 private IClient initClient(File sessdir, UserHandle userId,
264 ClientHandle clientHandle, File vamsasDocument) throws IOException,
265 InvalidSessionUrnException, InvalidSessionDocumentException {
266 IClient client = null;
268 VamsasSession vamsasSession = null;
269 if (vamsasDocument == null) {
270 vamsasSession = new VamsasSession(sessdir);
272 vamsasSession = new VamsasSession(sessdir, vamsasDocument);
274 getSessionManager().addSession(vamsasSession.getSessionUrn());
275 if (userId == null) {
276 // create a default userHandle
277 // userId = new UserHandle(System.getProperty("user.name",
278 // System.getProperty("USERNAME","Joe Doe")),
279 // System.getProperty("host.name",System.getProperty("HOSTNAME",
280 // "Unknown") ));// clientName, clientVersion, sessionPath);
281 userId = new UserHandle(null, null);
284 // FullName and organisation should not be null (otherwise UserHandle equals
285 // method raises an java.lang.NullPointerException )
286 // use current OS user and hostname, if null
287 if (userId.getFullName() == null) {
288 userId.setFullName(System.getProperty("user.name", System.getProperty(
289 "USERNAME", "Joe Doe")));
292 if (userId.getOrganization() == null) {
293 userId.setOrganization(System.getProperty("host.name", System
294 .getProperty("HOSTNAME", "Unknown")));
297 if (clientHandle == null)
298 clientHandle = new ClientHandle("SimpleVamsasClientApp", "0.1");
300 if (clientHandle.getClientName() == null) {
301 clientHandle.setClientName("SimpleVamsasClientApp");
303 if (clientHandle.getVersion() == null) {
304 clientHandle.setVersion("0.1");
308 // create simple client
309 client = new SimpleClient(userId, clientHandle, vamsasSession);
310 vamsasSession.addClient((SimpleClient) client);
311 vamsasSession.setSessionManager(this.getSessionManager());
316 * @see uk.ac.vamsas.client.IClientFactory#getIClient(uk.ac.vamsas.client.ClientHandle,
317 * uk.ac.vamsas.client.UserHandle)
319 public IClient getIClient(ClientHandle applicationHandle, UserHandle userId)
320 throws NoDefaultSessionException {
321 // create new session
322 // register SimpleClient and UserHandles in session
323 // create client instance
324 IClient client = null;
325 if (this.sessionArena == null)
327 "Improperly initialised SimpleClientFactory object - null sessionArena.");
329 ClientHandle clientHandle = applicationHandle;
330 // create default clientHandle with "SimpleVamsasClientApp","0.1",
331 if (clientHandle == null)
332 clientHandle = new ClientHandle("SimpleVamsasClientApp", "0.1");
334 if (clientHandle.getClientName() == null) {
335 clientHandle.setClientName("SimpleVamsasClientApp");
338 if (clientHandle.getVersion() == null) {
339 clientHandle.setVersion("0.1");
342 // check if any available session(s)
343 String[] availableSessions = this.getCurrentSessions();
344 if (availableSessions != null) {// there are available sessions
345 if (availableSessions.length > 1) {// more than one session if
346 // available... can not choose
348 // represents list of session as String
349 StringBuffer sessionURNs = new StringBuffer("");
350 for (int i = 0; i < availableSessions.length; i++) {
351 sessionURNs.append(availableSessions[i] + " ");
353 throw new NoDefaultSessionException(
354 "Several sessions available, please pick one: " + sessionURNs);
357 // check if only one session available. if yes, open it
358 if (availableSessions.length == 1) {
359 // only one session available, open it.
360 return this.getIClient(clientHandle, availableSessions[0]);
362 log.debug("No active session found");
365 // no session available - create a new one
367 client = clientInNewSession(userId, clientHandle, null);
368 } catch (Exception e) {
370 "IMPLEMENTATION ERROR: unexpected exception when creating a new session to connect to.",
377 * create a new session directory and possibly import an existing document
381 * @param clientHandle
382 * @param vamsasDocument
383 * null or a document file to copy into the new session
384 * @return null or a valid IClient instance
386 private IClient clientInNewSession(UserHandle userId,
387 ClientHandle clientHandle, File vamsasDocument)
388 throws InvalidSessionDocumentException, InvalidSessionUrnException {
390 IClient client = null;
392 // try and make a friendly session name
393 String sesspref = "";
394 if (vamsasDocument != null) {
395 sesspref = vamsasDocument.getName().replaceAll(
396 "([^-A-Za-z0-9]|\\.vdj)", "");
398 sesspref += (new java.util.Date()).toString().replaceAll("[^-A-Za-z0-9]",
400 // create sessionDirectory
401 File sessdir = new File(sessionArena, sesspref + ".simpleclient");
402 if (sessdir.exists()) {
403 // make a unique session name
404 sessdir = File.createTempFile(sesspref, ".simpleclient", sessionArena);
406 if (!sessdir.createNewFile()) {
408 "VAMSAS Implementation error : sesspref friendly session name is invalid on this platform - please tell the authors!");
411 log.debug("Creating new session directory");
412 if (!(sessdir.delete() && sessdir.mkdir()))
413 throw new IOException("Could not make session directory " + sessdir);
414 client = initClient(sessdir, userId, clientHandle, vamsasDocument);
415 } catch (IOException e) {
416 log.error("error while creating new IClient", e);
417 } catch (InvalidSessionUrnException e) {
419 "Unable to create new IClient. The new session urn is malformed.", e);
426 * @see uk.ac.vamsas.client.IClientFactory#getCurrentSessions()
428 public String[] getCurrentSessions() {
429 String[] sessions = null;
431 sessions = this.getSessionManager().getCurrentSessions();
432 } catch (IOException e) {
433 log.error("Unable to get available sessions", e);
440 * @return the sessionFile
442 private SimpleSessionManager getSessionManager() throws IOException {
443 if (this.sessionManager == null) {
444 this.sessionManager = new SimpleSessionManager(new File(
445 this.sessionArena, SESSION_LIST));
447 return this.sessionManager;
450 public IClient getNewSessionIClient(ClientHandle applicationHandle) {
452 return clientInNewSession(null, applicationHandle, null);
453 } catch (Exception e) {
454 log.error("Failed to create new session for app with default user.", e);
459 public IClient getNewSessionIClient(ClientHandle applicationHandle,
462 return clientInNewSession(userId, applicationHandle, null);
463 } catch (Exception e) {
464 log.error("Failed to create new session for app and user.", e);
469 private void checkImportedDocument(File vamsasDocument)
470 throws InvalidSessionDocumentException {
471 if (!vamsasDocument.exists()) {
472 throw new InvalidSessionDocumentException("File " + vamsasDocument
473 + " does not exist");
475 if (!vamsasDocument.canRead()) {
476 throw new InvalidSessionDocumentException("File " + vamsasDocument
477 + " does not exist");
481 public IClient openAsNewSessionIClient(ClientHandle applicationHandle,
482 File vamsasDocument) throws InvalidSessionDocumentException {
483 checkImportedDocument(vamsasDocument);
485 return clientInNewSession(null, applicationHandle, vamsasDocument);
486 } catch (InvalidSessionUrnException e) {
487 throw new InvalidSessionDocumentException("Unexpected exception", e);
491 public IClient openAsNewSessionIClient(ClientHandle applicationHandle,
492 UserHandle userId, File vamsasDocument)
493 throws InvalidSessionDocumentException {
494 checkImportedDocument(vamsasDocument);
496 return clientInNewSession(userId, applicationHandle, vamsasDocument);
497 } catch (InvalidSessionUrnException e) {
498 throw new InvalidSessionDocumentException("Unexpected exception", e);