/* * This file is part of the Vamsas Client version 0.1. * Copyright 2009 by Jim Procter, Iain Milne, Pierre Marguerite, * Andrew Waterhouse and Dominik Lindner. * * Earlier versions have also been incorporated into Jalview version 2.4 * since 2008, and TOPALi version 2 since 2007. * * The Vamsas Client is free software: you can redistribute it and/or modify * it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * The Vamsas Client is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License * along with the Vamsas Client. If not, see . */ package uk.ac.vamsas.client.simpleclient; import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import uk.ac.vamsas.client.ClientHandle; import uk.ac.vamsas.client.IClient; import uk.ac.vamsas.client.IClientFactory; import uk.ac.vamsas.client.InvalidSessionDocumentException; import uk.ac.vamsas.client.InvalidSessionUrnException; import uk.ac.vamsas.client.NoDefaultSessionException; import uk.ac.vamsas.client.SessionHandle; import uk.ac.vamsas.client.UserHandle; /** * * creates a session arena in the user home directory under .vamsas. Each * session has its own subdirectory. */ public class SimpleClientFactory implements IClientFactory { private static Log log = LogFactory.getLog(SimpleClientFactory.class); private File sessionArena = null; private String vamsasSubdirectoryName = ".vamsas"; private SimpleSessionManager sessionManager = null; private static final String SESSION_LIST = "sessions.obj"; // private String[] currentlyAvailableDessions = null; /** * default constructor - called by CreateClientFactory only. * * Inits the sessionarena to the directory .vamsas of the user home directory. * */ public SimpleClientFactory() throws IOException { // sessionArena // retrieves user home directory String userHomeDirectory = System.getProperty("user.home"); if (userHomeDirectory == null || userHomeDirectory.length() < 1) { new IOException("Unable to detect user home directory"); } String sessionArenaPath = userHomeDirectory.concat(File.separator .concat(this.vamsasSubdirectoryName)); this.initSessionArena(sessionArenaPath); // this.initFactoryObjects(); } /** * Create a client factory that works with sessions at the given path. * * @param path * path to directory called session arena, where will be created * session directories and session files. */ public SimpleClientFactory(String path) throws IOException { this.initSessionArena(path); } /** * Inits sessionArena to a given path. checks if path is valid. * * @param path * path to a directory to use * @throws IOException * if the path is incorrect */ private void initSessionArena(String path) throws IOException { // Check path is valid and read/writeable. File arenaFile = new File(path); if (!arenaFile.exists()) { if (!arenaFile.mkdirs()) { this.sessionArena = null; throw (new IOException("Unable to create a directory called " + path)); } } if (arenaFile.exists() && arenaFile.isDirectory() && arenaFile.canRead() && arenaFile.canWrite()) { this.sessionArena = arenaFile; } else { this.sessionArena = null; throw (new IOException("Cannot read and write to a directory called " + path)); } } /** * @see uk.ac.vamsas.client.IClientFactory#getIClient(uk.ac.vamsas.client.ClientHandle) * * Creates a IClient object, using default UserHandle with system * variables:"user.name" or "USERNAME")), "host.name" or "HOSTNAME" */ public IClient getIClient(ClientHandle applicationHandle) throws NoDefaultSessionException { // create a new session // register new ClientHandle in session // create SimpleClient instance return this.getIClient(applicationHandle, (UserHandle) null); } /** * the URN should be something like simpleclient:FILEPATH URL encoded * * @see uk.ac.vamsas.client.IClientFactory#getIClient(uk.ac.vamsas.client.ClientHandle, * java.lang.String) */ public IClient getIClient(ClientHandle applicationHandle, String sessionUrn) { // locate session from Urn // check that clientHandle is unique (with default user) - if not update the // clientHandle urn to make it unique. // wait for lock and attach to session // create SimpleClient instance log.debug("Trying to create session with URN " + sessionUrn); return this.getIClient(applicationHandle, null, sessionUrn); } private File convertSessionUrnToFile(String sessionUrn) throws InvalidSessionUrnException { if (sessionUrn == null) { log.debug("Incorrect URN: can not open session."); throw new InvalidSessionUrnException(); } SessionUrn urn = new SessionUrn(sessionUrn); return urn.asFile(); } /** * @see uk.ac.vamsas.client.IClientFactory#getIClient(uk.ac.vamsas.client.ClientHandle, * uk.ac.vamsas.client.UserHandle, java.lang.String) */ public IClient getIClient(ClientHandle applicationHandle, UserHandle userId, String sessionUrn) { // locate session from Urn // check Uniqueness of user + ClientHandle in the session. Update // clientHandle urn accordingly. // wait for lock, attach to session // create client instance IClient client = null; // TODO: implement 'opening stored session' opening mechanism // 1. existing session document URL is vdoc://... ? // 2. check for sessionUrn being of this form. // 3. if it is - locate the file and pass to new VamsasSession try { File sessionDirectory = this.convertSessionUrnToFile(sessionUrn); // create session log .debug("found session directory " + sessionDirectory.getAbsolutePath()); VamsasSession vamsasSession = new VamsasSession(sessionDirectory); /* * if (userId == null) { //create a default userHandle //with current OS * user and hostname userId = new * UserHandle(System.getProperty("user.name", * System.getProperty("USERNAME","Joe Doe")), * System.getProperty("host.name",System.getProperty("HOSTNAME", * "Unknown") ));// clientName, clientVersion, sessionPath); } * * * //create simple client client = new SimpleClient(userId, * applicationHandle, vamsasSession); */ client = this.initClient(sessionDirectory, userId, applicationHandle, null); } catch (MalformedURLException e) { log.error("error while creating new IClient: incorrect session urn", e); client = null; } catch (InvalidSessionDocumentException e) { log .error("error while creating new IClient: invalid session document", e); client = null; } catch (InvalidSessionUrnException e) { log.error("error while creating new IClient: incorrect session urn", e); client = null; } catch (IOException e) { log.error("error while creating new IClient: file access error", e); client = null; } return client; } /** * initialise the vamsas session state and create a SimpleClient object to * connect to it * * @param sessdir * newly created or existing session directory * @param userId * @param clientHandle * @param vamsasDocument * null or a document to pass to SimpleCLient to write into the * sessdir * @return the client * @throws IOException * if there are problems in session or client creation or if the * session already has a vamsasDocument * @throws InvalidSessionUrnException * for a malformed sessdir */ private IClient initClient(File sessdir, UserHandle userId, ClientHandle clientHandle, File vamsasDocument) throws IOException, InvalidSessionUrnException, InvalidSessionDocumentException { IClient client = null; // create session VamsasSession vamsasSession = null; if (vamsasDocument == null) { vamsasSession = new VamsasSession(sessdir); } else { vamsasSession = new VamsasSession(sessdir, vamsasDocument); } this.getSessionManager().addSession( new SessionHandle(new SessionUrn(vamsasSession).getSessionUrn())); if (userId == null) { // create a default userHandle // userId = new UserHandle(System.getProperty("user.name", // System.getProperty("USERNAME","Joe Doe")), // System.getProperty("host.name",System.getProperty("HOSTNAME", // "Unknown") ));// clientName, clientVersion, sessionPath); userId = new UserHandle(null, null); } // FullName and organisation should not be null (otherwise UserHandle equals // method raises an java.lang.NullPointerException ) // use current OS user and hostname, if null if (userId.getFullName() == null) { userId.setFullName(System.getProperty("user.name", System.getProperty( "USERNAME", "Joe Doe"))); } if (userId.getOrganization() == null) { userId.setOrganization(System.getProperty("host.name", System .getProperty("HOSTNAME", "Unknown"))); } if (clientHandle == null) clientHandle = new ClientHandle("SimpleVamsasClientApp", "0.1"); else { if (clientHandle.getClientName() == null) { clientHandle.setClientName("SimpleVamsasClientApp"); } if (clientHandle.getVersion() == null) { clientHandle.setVersion("0.1"); } } // create simple client client = new SimpleClient(userId, clientHandle, vamsasSession); vamsasSession.addClient((SimpleClient) client); vamsasSession.setSessionManager(this.getSessionManager()); return client; } /** * @see uk.ac.vamsas.client.IClientFactory#getIClient(uk.ac.vamsas.client.ClientHandle, * uk.ac.vamsas.client.UserHandle) */ public IClient getIClient(ClientHandle applicationHandle, UserHandle userId) throws NoDefaultSessionException { // create new session // register SimpleClient and UserHandles in session // create client instance IClient client = null; if (this.sessionArena == null) throw new Error( "Improperly initialised SimpleClientFactory object - null sessionArena."); ClientHandle clientHandle = applicationHandle; // create default clientHandle with "SimpleVamsasClientApp","0.1", if (clientHandle == null) clientHandle = new ClientHandle("SimpleVamsasClientApp", "0.1"); else { if (clientHandle.getClientName() == null) { clientHandle.setClientName("SimpleVamsasClientApp"); } if (clientHandle.getVersion() == null) { clientHandle.setVersion("0.1"); } } // check if any available session(s) String[] availableSessions = this.getCurrentSessions(); if (availableSessions != null) {// there are available sessions if (availableSessions.length > 1) {// more than one session if // available... can not choose // represents list of session as String StringBuffer sessionURNs = new StringBuffer(""); for (int i = 0; i < availableSessions.length; i++) { sessionURNs.append(availableSessions[i] + " "); } throw new NoDefaultSessionException( "Several sessions available, please pick one: " + sessionURNs); } // check if only one session available. if yes, open it if (availableSessions.length == 1) { // only one session available, open it. return this.getIClient(clientHandle, availableSessions[0]); } else { log.debug("No active session found"); } } // no session available - create a new one try { client = clientInNewSession(userId, clientHandle, null); } catch (Exception e) { throw new Error( "IMPLEMENTATION ERROR: unexpected exception when creating a new session to connect to.", e); } return client; } /** * create a new session directory and possibly import an existing document * into it * * @param userId * @param clientHandle * @param vamsasDocument * null or a document file to copy into the new session * @return null or a valid IClient instance */ private IClient clientInNewSession(UserHandle userId, ClientHandle clientHandle, File vamsasDocument) throws InvalidSessionDocumentException, InvalidSessionUrnException { IClient client = null; try { // try and make a friendly session name String sesspref = ""; if (vamsasDocument != null) { sesspref = vamsasDocument.getName().replaceAll( "([^-A-Za-z0-9]|\\.vdj)", ""); } sesspref += (new java.util.Date()).toString().replaceAll("[^-A-Za-z0-9]", "_"); // create sessionDirectory File sessdir = new File(sessionArena, sesspref + ".simpleclient"); if (sessdir.exists()) { // make a unique session name sessdir = File.createTempFile(sesspref, ".simpleclient", sessionArena); } else { if (!sessdir.createNewFile()) { throw new Error( "VAMSAS Implementation error : sesspref friendly session name is invalid on this platform - please tell the authors!"); } } log.debug("Creating new session directory"); if (!(sessdir.delete() && sessdir.mkdir())) throw new IOException("Could not make session directory " + sessdir); client = initClient(sessdir, userId, clientHandle, vamsasDocument); } catch (IOException e) { log.error("error while creating new IClient", e); } catch (InvalidSessionUrnException e) { log.error( "Unable to create new IClient. The new session urn is malformed.", e); } return client; } /** * @see uk.ac.vamsas.client.IClientFactory#getCurrentSessions() */ public String[] getCurrentSessions() { String[] sessions = null; try { sessions = this.getSessionManager().getCurrentSessions(); } catch (IOException e) { log.error("Unable to get available sessions", e); sessions = null; } return sessions; } /** * @return the sessionFile */ private SimpleSessionManager getSessionManager() throws IOException { if (this.sessionManager == null) { this.sessionManager = new SimpleSessionManager(new File( this.sessionArena, SESSION_LIST)); } return this.sessionManager; } public IClient getNewSessionIClient(ClientHandle applicationHandle) { try { return clientInNewSession(null, applicationHandle, null); } catch (Exception e) { log.error("Failed to create new session for app with default user.", e); } return null; } public IClient getNewSessionIClient(ClientHandle applicationHandle, UserHandle userId) { try { return clientInNewSession(userId, applicationHandle, null); } catch (Exception e) { log.error("Failed to create new session for app and user.", e); } return null; } private void checkImportedDocument(File vamsasDocument) throws InvalidSessionDocumentException { if (!vamsasDocument.exists()) { throw new InvalidSessionDocumentException("File " + vamsasDocument + " does not exist"); } if (!vamsasDocument.canRead()) { throw new InvalidSessionDocumentException("File " + vamsasDocument + " does not exist"); } } public IClient openAsNewSessionIClient(ClientHandle applicationHandle, File vamsasDocument) throws InvalidSessionDocumentException { checkImportedDocument(vamsasDocument); try { return clientInNewSession(null, applicationHandle, vamsasDocument); } catch (InvalidSessionUrnException e) { throw new InvalidSessionDocumentException("Unexpected exception", e); } } public IClient openAsNewSessionIClient(ClientHandle applicationHandle, UserHandle userId, File vamsasDocument) throws InvalidSessionDocumentException { checkImportedDocument(vamsasDocument); try { return clientInNewSession(userId, applicationHandle, vamsasDocument); } catch (InvalidSessionUrnException e) { throw new InvalidSessionDocumentException("Unexpected exception", e); } } }