todo for importing stored session as a new session
[vamsas.git] / src / uk / ac / vamsas / client / simpleclient / SimpleClientFactory.java
1 /**
2  * 
3  * VAMSAS Project
4  *
5  * 
6  * Dec 13, 2006 
7  *
8  */
9
10 package uk.ac.vamsas.client.simpleclient;
11
12 import java.io.File;
13
14 import java.io.IOException;
15 import java.net.MalformedURLException;
16
17 import org.apache.commons.logging.Log;
18 import org.apache.commons.logging.LogFactory;
19
20 import uk.ac.vamsas.client.ClientHandle;
21 import uk.ac.vamsas.client.IClient;
22 import uk.ac.vamsas.client.IClientFactory;
23 import uk.ac.vamsas.client.InvalidSessionUrnException;
24 import uk.ac.vamsas.client.NoDefaultSessionException;
25 import uk.ac.vamsas.client.SessionHandle;
26 import uk.ac.vamsas.client.UserHandle;
27
28 /**
29  * 
30  * creates a session arena in the user home directory under .vamsas. Each
31  * session has its own subdirectory.
32  */
33 public class SimpleClientFactory implements IClientFactory {
34
35   private static Log log = LogFactory.getLog(SimpleClientFactory.class);
36
37   private File sessionArena = null;
38
39   private String vamsasSubdirectoryName = ".vamsas";
40
41   private SimpleSessionManager sessionManager = null;
42
43   private static final String SESSION_LIST = "sessions.obj";
44
45   // private String[] currentlyAvailableDessions = null;
46
47   /**
48    * default constructor - called by CreateClientFactory only.
49    * 
50    * Inits the sessionarena to the directory .vamsas of the user home directory.
51    * 
52    */
53   public SimpleClientFactory() throws IOException {
54     // sessionArena
55
56     // retrieves user home directory
57     String userHomeDirectory = System.getProperty("user.home");
58     if (userHomeDirectory == null || userHomeDirectory.length() < 1) {
59       new IOException("Unable to detect user home directory");
60     }
61     String sessionArenaPath = userHomeDirectory.concat(File.separator
62         .concat(this.vamsasSubdirectoryName));
63
64     this.initSessionArena(sessionArenaPath);
65     // this.initFactoryObjects();
66   }
67
68   /**
69    * Create a client factory that works with sessions at the given path.
70    * 
71    * @param path
72    *          path to directory called session arena, where will be created
73    *          session directories and session files.
74    */
75   public SimpleClientFactory(String path) throws IOException {
76     this.initSessionArena(path);
77   }
78
79   /**
80    * Inits sessionArena to a given path. checks if path is valid.
81    * 
82    * @param path
83    *          path to a directory to use
84    * @throws IOException
85    *           if the path is incorrect
86    */
87   private void initSessionArena(String path) throws IOException {
88     // Check path is valid and read/writeable.
89     File arenaFile = new File(path);
90     if (!arenaFile.exists()) {
91       if (!arenaFile.mkdirs()) {
92         this.sessionArena = null;
93         throw (new IOException("Unable to create a directory called " + path));
94       }
95     }
96     if (arenaFile.exists() && arenaFile.isDirectory() && arenaFile.canRead()
97         && arenaFile.canWrite()) {
98       this.sessionArena = arenaFile;
99     } else {
100       this.sessionArena = null;
101       throw (new IOException("Cannot read and write to a directory called "
102           + path));
103     }
104   }
105
106   /**
107    * @see uk.ac.vamsas.client.IClientFactory#getIClient(uk.ac.vamsas.client.ClientHandle)
108    * 
109    * Creates a IClient object, using default UserHandle with system
110    * variables:"user.name" or "USERNAME")), "host.name" or "HOSTNAME"
111    */
112   public IClient getIClient(ClientHandle applicationHandle)
113       throws NoDefaultSessionException {
114     // create a new session
115     // register new ClientHandle in session
116     // create SimpleClient instance
117     return this.getIClient(applicationHandle, (UserHandle) null);
118   }
119
120   /**
121    * the URN should be something like simpleclient:FILEPATH URL encoded
122    * 
123    * @see uk.ac.vamsas.client.IClientFactory#getIClient(uk.ac.vamsas.client.ClientHandle,
124    *      java.lang.String)
125    */
126   public IClient getIClient(ClientHandle applicationHandle, String sessionUrn) {
127     // locate session from Urn
128     // check that clientHandle is unique (with default user) - if not update the
129     // clientHandle urn to make it unique.
130     // wait for lock and attach to session
131     // create SimpleClient instance
132     log.debug("Trying to create session with URN " + sessionUrn);
133     return this.getIClient(applicationHandle, null, sessionUrn);
134
135   }
136
137   private File convertSessionUrnToFile(String sessionUrn)
138       throws InvalidSessionUrnException {
139     if (sessionUrn == null) {
140       log.debug("Incorrect URN: can not open session.");
141       throw new InvalidSessionUrnException();
142     }
143
144     SessionUrn urn = new SessionUrn(sessionUrn);
145     return urn.asFile();
146
147   }
148
149   /**
150    * @see uk.ac.vamsas.client.IClientFactory#getIClient(uk.ac.vamsas.client.ClientHandle,
151    *      uk.ac.vamsas.client.UserHandle, java.lang.String)
152    */
153   public IClient getIClient(ClientHandle applicationHandle, UserHandle userId,
154       String sessionUrn) {
155     // locate session from Urn
156     // check Uniqueness of user + ClientHandle in the session. Update
157     // clientHandle urn accordingly.
158     // wait for lock, attach to session
159     // create client instance
160     IClient client = null;
161
162     // TODO: implement 'opening stored session' opening mechanism
163     // 1. existing session document URL is vdoc://... ?
164     // 2. check for sessionUrn being of this form.
165     // 3. if it is - locate the file and pass to new VamsasSession
166
167     try {
168       File sessionDirectory = this.convertSessionUrnToFile(sessionUrn);
169       // create session
170       log
171           .debug("found session directory "
172               + sessionDirectory.getAbsolutePath());
173       VamsasSession vamsasSession = new VamsasSession(sessionDirectory);
174       
175       /*
176        * if (userId == null) { //create a default userHandle //with current OS
177        * user and hostname userId = new UserHandle(System.getProperty("user.name",
178        * System.getProperty("USERNAME","Joe Doe")),
179        * System.getProperty("host.name",System.getProperty("HOSTNAME", "Unknown")
180        * ));// clientName, clientVersion, sessionPath); }
181        * 
182        * 
183        * //create simple client client = new SimpleClient(userId,
184        * applicationHandle, vamsasSession);
185        */
186       client = this.initClient(sessionDirectory, userId, applicationHandle);
187     } catch (MalformedURLException e) {
188       log.error("error while creating new IClient: incorrect session urn", e);
189       client = null;
190
191     } catch (InvalidSessionUrnException e) {
192       log.error("error while creating new IClient: incorrect session urn", e);
193       client = null;
194     } catch (IOException e) {
195       log.error("error while creating new IClient: file access error", e);
196       client = null;
197     }
198     return client;
199   }
200
201   private IClient initClient(File sessdir, UserHandle userId,
202       ClientHandle clientHandle) throws IOException, InvalidSessionUrnException {
203     IClient client = null;
204     // create session
205     VamsasSession vamsasSession = new VamsasSession(sessdir);
206
207     this.getSessionManager().addSession(
208         new SessionHandle(new SessionUrn(vamsasSession).getSessionUrn()));
209     if (userId == null) {
210       // create a default userHandle
211       // userId = new UserHandle(System.getProperty("user.name",
212       // System.getProperty("USERNAME","Joe Doe")),
213       // System.getProperty("host.name",System.getProperty("HOSTNAME",
214       // "Unknown") ));// clientName, clientVersion, sessionPath);
215       userId = new UserHandle(null, null);
216     }
217
218     // FullName and organisation should not be null (otherwise UserHandle equals
219     // method raises an java.lang.NullPointerException )
220     // use current OS user and hostname, if null
221     if (userId.getFullName() == null) {
222       userId.setFullName(System.getProperty("user.name", System.getProperty(
223           "USERNAME", "Joe Doe")));
224     }
225
226     if (userId.getOrganization() == null) {
227       userId.setOrganization(System.getProperty("host.name", System
228           .getProperty("HOSTNAME", "Unknown")));
229     }
230
231     if (clientHandle == null)
232       clientHandle = new ClientHandle("SimpleVamsasClientApp", "0.1");
233     else {
234       if (clientHandle.getClientName() == null) {
235         clientHandle.setClientName("SimpleVamsasClientApp");
236       }
237       if (clientHandle.getVersion() == null) {
238         clientHandle.setVersion("0.1");
239       }
240     }
241
242     // create simple client
243     client = new SimpleClient(userId, clientHandle, vamsasSession);
244     vamsasSession.addClient((SimpleClient) client);
245     vamsasSession.setSessionManager(this.getSessionManager());
246     return client;
247   }
248
249   /**
250    * @see uk.ac.vamsas.client.IClientFactory#getIClient(uk.ac.vamsas.client.ClientHandle,
251    *      uk.ac.vamsas.client.UserHandle)
252    */
253   public IClient getIClient(ClientHandle applicationHandle, UserHandle userId)
254       throws NoDefaultSessionException {
255     // create new session
256     // register SimpleClient and UserHandles in session
257     // create client instance
258     IClient client = null;
259     if (this.sessionArena == null)
260       throw new Error(
261           "Improperly initialised SimpleClientFactory object - null sessionArena.");
262
263     ClientHandle clientHandle = applicationHandle;
264     // create default clientHandle with "SimpleVamsasClientApp","0.1",
265     if (clientHandle == null)
266       clientHandle = new ClientHandle("SimpleVamsasClientApp", "0.1");
267     else {
268       if (clientHandle.getClientName() == null) {
269         clientHandle.setClientName("SimpleVamsasClientApp");
270       }
271
272       if (clientHandle.getVersion() == null) {
273         clientHandle.setVersion("0.1");
274       }
275     }
276     // check if any available session(s)
277     String[] availableSessions = this.getCurrentSessions();
278     if (availableSessions != null) {// there are available sessions
279       if (availableSessions.length > 1) {// more than one session if available... can not choose
280
281         // represents list of session as String
282         StringBuffer sessionURNs = new StringBuffer("");
283         for (int i = 0; i < availableSessions.length; i++) {
284           sessionURNs.append(availableSessions[i] + " ");
285         }
286         throw new NoDefaultSessionException(
287             "Several sessions available, please pick one: " + sessionURNs);
288       }
289
290       // check if only one session available. if yes, open it
291       if (availableSessions.length == 1) {
292         // only one session available, open it.
293         return this.getIClient(clientHandle, availableSessions[0]);
294       } else {
295         log.debug("No active session found");
296       }
297     }
298     // no session available - create a new one
299
300     client = clientInNewSession(userId, clientHandle);
301     return client;
302   }
303
304   /**
305    * 
306    * @param userId
307    * @param clientHandle
308    * @return
309    */
310   private IClient clientInNewSession(UserHandle userId,
311       ClientHandle clientHandle) {
312
313     IClient client = null;
314     try {
315       // create sessionDirectory
316       File sessdir = File.createTempFile("sess", ".simpleclient",
317           this.sessionArena);
318       log.debug("Creating new session  directory");
319       if (!(sessdir.delete() && sessdir.mkdir()))
320         throw new IOException("Could not make session directory " + sessdir);
321       client = this.initClient(sessdir, userId, clientHandle);
322     } catch (IOException e) {
323       log.error("error while creating new IClient", e);
324     } catch (InvalidSessionUrnException e) {
325       log.error("Unable to create new IClient. The session urn is incorrect ",
326           e);
327     }
328
329     return client;
330   }
331
332   /**
333    * @see uk.ac.vamsas.client.IClientFactory#getCurrentSessions()
334    */
335   public String[] getCurrentSessions() {
336     String[] sessions = null;
337     try {
338       sessions = this.getSessionManager().getCurrentSessions();
339     } catch (IOException e) {
340       log.error("Unable to get available sessions", e);
341       sessions = null;
342     }
343     return sessions;
344   }
345
346   /**
347    * @return the sessionFile
348    */
349   private SimpleSessionManager getSessionManager() throws IOException {
350     if (this.sessionManager == null) {
351       this.sessionManager = new SimpleSessionManager(new File(
352           this.sessionArena, SESSION_LIST));
353     }
354     return this.sessionManager;
355   }
356
357   public IClient getNewSessionIClient(ClientHandle applicationHandle) {
358     return clientInNewSession(null, applicationHandle);
359   }
360
361   public IClient getNewSessionIClient(ClientHandle applicationHandle,
362       UserHandle userId) {
363     return clientInNewSession(userId, applicationHandle);
364   }
365
366 }