2 * This file is part of the Vamsas Client version 0.2.
3 * Copyright 2010 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
256 * @param preferredName - name to use instead of vamsasDocument path when creating new session URN
258 * @throws IOException
259 * if there are problems in session or client creation or if the
260 * session already has a vamsasDocument
261 * @throws InvalidSessionUrnException
262 * for a malformed sessdir
264 private IClient initClient(File sessdir, UserHandle userId,
265 ClientHandle clientHandle, File vamsasDocument, String preferredName) throws IOException,
266 InvalidSessionUrnException, InvalidSessionDocumentException {
267 IClient client = null;
269 VamsasSession vamsasSession = null;
270 if (vamsasDocument == null) {
271 vamsasSession = new VamsasSession(sessdir);
273 vamsasSession = new VamsasSession(sessdir, vamsasDocument,preferredName);
275 getSessionManager().addSession(vamsasSession.getSessionUrn());
276 if (userId == null) {
277 // create a default userHandle
278 // userId = new UserHandle(System.getProperty("user.name",
279 // System.getProperty("USERNAME","Joe Doe")),
280 // System.getProperty("host.name",System.getProperty("HOSTNAME",
281 // "Unknown") ));// clientName, clientVersion, sessionPath);
282 userId = new UserHandle(null, null);
285 // FullName and organisation should not be null (otherwise UserHandle equals
286 // method raises an java.lang.NullPointerException )
287 // use current OS user and hostname, if null
288 if (userId.getFullName() == null) {
289 userId.setFullName(System.getProperty("user.name", System.getProperty(
290 "USERNAME", "Joe Doe")));
293 if (userId.getOrganization() == null) {
294 userId.setOrganization(System.getProperty("host.name", System
295 .getProperty("HOSTNAME", "Unknown")));
298 if (clientHandle == null)
299 clientHandle = new ClientHandle("SimpleVamsasClientApp", "0.1");
301 if (clientHandle.getClientName() == null) {
302 clientHandle.setClientName("SimpleVamsasClientApp");
304 if (clientHandle.getVersion() == null) {
305 clientHandle.setVersion("0.1");
309 // create simple client
310 client = new SimpleClient(userId, clientHandle, vamsasSession);
311 vamsasSession.addClient((SimpleClient) client);
312 vamsasSession.setSessionManager(this.getSessionManager());
317 * @see uk.ac.vamsas.client.IClientFactory#getIClient(uk.ac.vamsas.client.ClientHandle,
318 * uk.ac.vamsas.client.UserHandle)
320 public IClient getIClient(ClientHandle applicationHandle, UserHandle userId)
321 throws NoDefaultSessionException {
322 // create new session
323 // register SimpleClient and UserHandles in session
324 // create client instance
325 IClient client = null;
326 if (this.sessionArena == null)
328 "Improperly initialised SimpleClientFactory object - null sessionArena.");
330 ClientHandle clientHandle = applicationHandle;
331 // create default clientHandle with "SimpleVamsasClientApp","0.1",
332 if (clientHandle == null)
333 clientHandle = new ClientHandle("SimpleVamsasClientApp", "0.1");
335 if (clientHandle.getClientName() == null) {
336 clientHandle.setClientName("SimpleVamsasClientApp");
339 if (clientHandle.getVersion() == null) {
340 clientHandle.setVersion("0.1");
343 // check if any available session(s)
344 String[] availableSessions = this.getCurrentSessions();
345 if (availableSessions != null) {// there are available sessions
346 if (availableSessions.length > 1) {// more than one session if
347 // available... can not choose
349 // represents list of session as String
350 StringBuffer sessionURNs = new StringBuffer("");
351 for (int i = 0; i < availableSessions.length; i++) {
352 sessionURNs.append(availableSessions[i] + " ");
354 throw new NoDefaultSessionException(
355 "Several sessions available, please pick one: " + sessionURNs);
358 // check if only one session available. if yes, open it
359 if (availableSessions.length == 1) {
360 // only one session available, open it.
361 return this.getIClient(clientHandle, availableSessions[0]);
363 log.debug("No active session found");
366 // no session available - create a new one
368 client = clientInNewSession(userId, clientHandle, null,null);
369 } catch (Exception e) {
371 "IMPLEMENTATION ERROR: unexpected exception when creating a new session to connect to.",
378 * create a new session directory and possibly import an existing document
382 * @param clientHandle
383 * @param vamsasDocument
384 * null or a document file to copy into the new session
385 * @param preferredName - name to be used as base for the new session URN
386 * @return null or a valid IClient instance
388 private IClient clientInNewSession(UserHandle userId,
389 ClientHandle clientHandle, File vamsasDocument, String preferredName)
390 throws InvalidSessionDocumentException, InvalidSessionUrnException {
392 IClient client = null;
394 // try and make a friendly session name
395 String sesspref = "";
396 if (vamsasDocument != null) {
397 if (preferredName!=null)
399 sesspref = preferredName.replaceAll(
400 "([^-A-Za-z0-9]|\\.vdj)", "");
402 sesspref = vamsasDocument.getName().replaceAll(
403 "([^-A-Za-z0-9]|\\.vdj)", "");
406 sesspref += (new java.util.Date()).toString().replaceAll("[^-A-Za-z0-9]",
408 // create sessionDirectory
409 File sessdir = new File(sessionArena, sesspref + ".simpleclient");
410 if (sessdir.exists()) {
411 // make a unique session name
412 sessdir = File.createTempFile(sesspref, ".simpleclient", sessionArena);
414 if (!sessdir.createNewFile()) {
416 "VAMSAS Implementation error : sesspref friendly session name is invalid on this platform - please tell the authors!");
419 log.debug("Creating new session directory");
420 if (!(sessdir.delete() && sessdir.mkdir()))
421 throw new IOException("Could not make session directory " + sessdir);
422 client = initClient(sessdir, userId, clientHandle, vamsasDocument, preferredName);
423 } catch (IOException e) {
424 log.error("error while creating new IClient", e);
425 } catch (InvalidSessionUrnException e) {
427 "Unable to create new IClient. The new session urn is malformed.", e);
434 * @see uk.ac.vamsas.client.IClientFactory#getCurrentSessions()
436 public String[] getCurrentSessions() {
437 String[] sessions = null;
439 sessions = this.getSessionManager().getCurrentSessions();
440 } catch (IOException e) {
441 log.error("Unable to get available sessions", e);
448 * @return the sessionFile
450 private SimpleSessionManager getSessionManager() throws IOException {
451 if (this.sessionManager == null) {
452 this.sessionManager = new SimpleSessionManager(new File(
453 this.sessionArena, SESSION_LIST));
455 return this.sessionManager;
458 public IClient getNewSessionIClient(ClientHandle applicationHandle) {
460 return clientInNewSession(null, applicationHandle, null,null);
461 } catch (Exception e) {
462 log.error("Failed to create new session for app with default user.", e);
467 public IClient getNewSessionIClient(ClientHandle applicationHandle,
470 return clientInNewSession(userId, applicationHandle, null,null);
471 } catch (Exception e) {
472 log.error("Failed to create new session for app and user.", e);
477 private void checkImportedDocument(File vamsasDocument)
478 throws InvalidSessionDocumentException {
479 if (!vamsasDocument.exists()) {
480 throw new InvalidSessionDocumentException("File " + vamsasDocument
481 + " does not exist");
483 if (!vamsasDocument.canRead()) {
484 throw new InvalidSessionDocumentException("File " + vamsasDocument
485 + " does not exist");
489 public IClient openAsNewSessionIClient(ClientHandle applicationHandle,
490 File vamsasDocument) throws InvalidSessionDocumentException {
491 checkImportedDocument(vamsasDocument);
493 return clientInNewSession(null, applicationHandle, vamsasDocument,null);
494 } catch (InvalidSessionUrnException e) {
495 throw new InvalidSessionDocumentException("Unexpected exception", e);
499 public IClient openAsNewSessionIClient(ClientHandle applicationHandle,
500 UserHandle userId, File vamsasDocument)
501 throws InvalidSessionDocumentException {
502 checkImportedDocument(vamsasDocument);
504 return clientInNewSession(userId, applicationHandle, vamsasDocument,null);
505 } catch (InvalidSessionUrnException e) {
506 throw new InvalidSessionDocumentException("Unexpected exception", e);
510 public IClient openAsNewSessionIClient(ClientHandle applicationHandle,
511 File vamsasDocument, String sessionName)
512 throws InvalidSessionDocumentException {
513 checkImportedDocument(vamsasDocument);
515 return clientInNewSession(null, applicationHandle, vamsasDocument, sessionName);
516 } catch (InvalidSessionUrnException e) {
517 throw new InvalidSessionDocumentException("Unexpected exception", e);
521 public IClient openAsNewSessionIClient(ClientHandle applicationHandle,
522 UserHandle userId, File vamsasDocument, String sessionName)
523 throws InvalidSessionDocumentException {
524 checkImportedDocument(vamsasDocument);
526 return clientInNewSession(userId, applicationHandle, vamsasDocument, sessionName);
527 } catch (InvalidSessionUrnException e) {
528 throw new InvalidSessionDocumentException("Unexpected exception", e);