partially implemented simpleclient.EventGenerator
[vamsas.git] / src / org / vamsas / client / simpleclient / VamsasSession.java
1 package org.vamsas.client.simpleclient;
2
3 import java.io.File;
4 import java.io.IOException;
5
6 import org.apache.commons.logging.Log;
7 import org.apache.commons.logging.LogFactory;
8 import org.apache.log4j.Appender;
9 import org.apache.log4j.Logger;
10 import org.apache.log4j.FileAppender;
11 /**
12  * 
13  * Vamsas client is intialised with a path to create live session directories. 
14  * This path may contain a vamsas.properties file 
15  * that sets additional parameters (otherwise client 
16  * just uses the one on the classpath).
17  * 
18  * A vamsas session consists of :
19  *  SessionDir - translates to urn of a live session.
20  *  Contains: Vamsas Document (as a jar), Session client list file, 
21  *  both of which may be locked, and additional 
22  *  temporary versions of these files when write 
23  *  operations are taking place.
24  * 
25  * Zip file entries
26  *  - vamsasdocument.xml : core info
27  *  one or more:
28  *  - <applicationname>.version.sessionnumber.raw (string given in vamsasdocument.xml applicationData entry)
29  *  
30  * Lockfile
31  *  - filename given in the vamsasdocument.xml. Should be checked for validity by any client and rewritten if necessary. 
32  *    The lockfile can point to the jar itself.
33  * Mode of operation.
34  * Initially - documentHandler either:
35  *  - creates a zip for a new session for the client
36  *  - connect to an existing session zip 
37  *   1. reads session urn file
38  *   2. waits for lock
39  *   3. examines session - decide whether to create new application data slice or connect to one stored in session.
40  *   4. writes info into session file
41  *   5. releases lock and generates local client events.
42  *   6. Creates Watcher thread to generate events.
43  * 
44  * During the session
45  *  - Update watcher checks for file change - 
46  * 
47  */
48
49 public class VamsasSession {
50   /**
51    * Holds the file handlers and watchers for a session.
52    */
53   /**
54    * TODO: make sessionDir signature to allow VamsasSession instances to recognise the form of the directory
55    */
56   /**
57    * indicator file for informing other processes that 
58    * they should finalise their vamsas datasets for 
59    * storing in a vamsas archive.
60    */
61   public static final String CLOSEANDSAVE_FILE="exiting";
62   /**
63    * log file location
64    */
65   public static final String SESSION_LOG="Log.txt";
66   private static Log log = LogFactory.getLog(VamsasSession.class);
67   protected Logger slog = Logger.getLogger("org.vamsas.client.SessionLog");
68   /**
69    * setup the sessionLog using Log4j.
70    * @throws IOException
71    */
72   private void initLog() throws IOException {
73     Appender app = slog.getAppender("SESSION_LOG");
74     slog.addAppender(new FileAppender(app.getLayout(), new File(sessionDir, SESSION_LOG).getAbsolutePath()));
75   }
76   
77   /**
78    * the sessionDir is given as the session location for new clients.
79    */
80   File sessionDir;
81   /**
82    * holds the list of attached clients
83    */
84   ClientsFile clist;
85   public static final String CLIENT_LIST="Clients.obj";
86   /**
87    * holds the data
88    */
89   VamsasFile vamArchive; 
90   public static final String VAMSAS_OBJ="VamDoc.jar";
91   
92   /**
93    * sets up the vamsas session files and watchers in sessionDir
94    * @param sessionDir
95    */
96   protected VamsasSession(File sessionDir) throws IOException {
97     if (sessionDir==null)
98       throw new Error("Null directory for VamsasSession.");
99     if (sessionDir.exists()) {
100       if (!sessionDir.isDirectory() || !sessionDir.canWrite() || sessionDir.canRead())
101         throw new IOException("Cannot access '"+sessionDir+"' as a read/writable Directory.");
102       if (checkSessionFiles(sessionDir)) {
103         // session files exist in the directory
104         this.sessionDir = sessionDir;
105         initSessionObjects();
106         slog.debug("Initialising additional VamsasSession instance");
107         log.debug("Attached to VamsasSession in "+sessionDir);
108       } 
109     } else {
110       // start from scratch
111       if (!sessionDir.mkdir())
112         throw new IOException("Failed to make VamsasSession directory in "+sessionDir);
113       this.sessionDir = sessionDir; 
114       createSessionFiles();
115       initSessionObjects();
116       slog.debug("Session directory created.");
117       log.debug("Initialised VamsasSession in "+sessionDir);
118     }
119   }
120   /**
121    * tests presence of existing sessionfiles files in dir
122    * @param dir
123    * @return
124    */
125   private boolean checkSessionFiles(File dir) throws IOException {
126     File c_file = new File(dir,CLIENT_LIST);
127     File v_doc = new File(dir,VAMSAS_OBJ);
128     if (c_file.exists() && v_doc.exists())
129       return true;
130     return false;
131   }
132   /**
133    * create new empty files in dir
134    *
135    */
136   private void createSessionFiles() throws IOException {
137     if (sessionDir==null)
138       throw new IOException("Invalid call to createSessionFiles() with null sessionDir");
139     File c_file = new File(sessionDir,CLIENT_LIST);
140     File v_doc = new File(sessionDir,VAMSAS_OBJ);
141     if (c_file.createNewFile())
142       log.debug("Created new ClientFile "+c_file); // don't care if this works or not
143     if (v_doc.createNewFile())
144       log.debug("Created new Vamsas Session Document File "+v_doc); 
145   }
146   /**
147    * construct SessionFile objects and watchers for each
148    */
149   private void initSessionObjects() throws IOException {
150     if (clist!=null || vamArchive!=null)
151       throw new IOException("initSessionObjects called for initialised VamsasSession object.");
152     clist = new ClientsFile(new File(sessionDir,CLIENT_LIST));
153     vamArchive = new VamsasFile(new File(sessionDir,VAMSAS_OBJ));
154   }
155   /**
156    * make a new watcher object for the clientFile
157    * @return new ClientFile watcher instance
158    */
159   public FileWatcher getClientWatcher() {
160     return new FileWatcher(clist.sessionFile);
161   }
162   /**
163    * make a new watcher object for the vamsas Document
164    * @return new ClientFile watcher instance
165    */
166   public FileWatcher getDocWatcher() {
167     return new FileWatcher(vamArchive.sessionFile);
168   }
169
170   /**
171    * make a new watcher object for the messages file
172    * @return new watcher instance
173    */
174   public FileWatcher getStoreWatcher() {
175     return new FileWatcher(new File(CLOSEANDSAVE_FILE));
176   }
177   
178 }
179
180