KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > remoting > callback > CallbackStore


1 /*
2  * JBoss, the OpenSource J2EE webOS
3  *
4  * Distributable under LGPL license.
5  * See terms of license at gnu.org.
6  */

7 package org.jboss.remoting.callback;
8
9 import java.io.File JavaDoc;
10 import java.io.FileInputStream JavaDoc;
11 import java.io.FileOutputStream JavaDoc;
12 import java.io.FilenameFilter JavaDoc;
13 import java.io.IOException JavaDoc;
14 import java.io.ObjectInputStream JavaDoc;
15 import java.io.ObjectOutputStream JavaDoc;
16 import java.io.Serializable JavaDoc;
17 import java.util.Map JavaDoc;
18 import org.jboss.logging.Logger;
19
20 /**
21  * Acts as a persistent list which writes Serializable objects to disk and will retrieve them
22  * in same order in which they were added (FIFO). Each file will be named according to the current
23  * time (using System.currentTimeMillis() with the file suffix specified (see below). When the
24  * object is read and returned by calling the getNext() method, the file on disk for that object will
25  * be deleted. If for some reason the store VM crashes, the objects will still be available upon next startup.
26  * <p/>
27  * The attributes to make sure to configure are:
28  * <p/>
29  * file path - this determins which directory to write the objects. The default value is the property value
30  * of 'jboss.server.data.dir' and if this is not set, then will be 'data'. For example, might
31  * be /jboss/server/default/data.<p>
32  * file suffix - the file suffix to use for the file written for each object stored.<p>
33  * <p/>
34  * This is also a service mbean, so can be run as a service within JBoss AS or stand alone.
35  *
36  * @author <a HREF="mailto:tom@jboss.org">Tom Elrod</a>
37  */

38 public class CallbackStore implements CallbackStoreMBean
39 {
40    private String JavaDoc filePath = null;
41    private String JavaDoc fileSuffix = "ser";
42
43    private boolean isStarted = false;
44    private boolean purgeOnShutdown = false;
45
46    public static final String JavaDoc FILE_PATH_KEY = "StoreFilePath";
47    public static final String JavaDoc FILE_SUFFIX_KEY = "StoreFileSuffix";
48
49    private static final Logger log = Logger.getLogger(CallbackStore.class);
50
51    /**
52     * Default store constructor.
53     */

54    public CallbackStore()
55    {
56
57    }
58
59    /**
60     * Store constructor.
61     *
62     * @param purgeOnDestroy if true, will remove all persisted objects from disk on when destroy() is called, else
63     * will leave the files (which is the default behaviour).
64     */

65    public CallbackStore(boolean purgeOnDestroy)
66    {
67       this.purgeOnShutdown = purgeOnDestroy;
68    }
69
70    /**
71     * Will get the file path value (if not already set will just use the
72     * default setting) and will create the directory specified by the file path
73     * if it does not already exist.
74     *
75     * @throws Exception
76     */

77    public void start() throws Exception JavaDoc
78    {
79       if(!isStarted)
80       {
81          // need to figure the best place to store on disk
82
if(filePath == null)
83          {
84             filePath = System.getProperty("jboss.server.data.dir", "data");
85          }
86          File JavaDoc storeFile = new File JavaDoc(filePath);
87          if(!storeFile.exists())
88          {
89             boolean madeDir = storeFile.mkdirs();
90             if(!madeDir)
91             {
92                throw new IOException JavaDoc("Can not create directory for store. Path given: " + filePath);
93             }
94          }
95          isStarted = true;
96       }
97    }
98
99    /**
100     * Sets if store should clean up persisted files when shutdown (destroy()).
101     *
102     * @param purgeOnShutdown
103     */

104    public void setPurgeOnShutdown(boolean purgeOnShutdown)
105    {
106       this.purgeOnShutdown = purgeOnShutdown;
107    }
108
109    /**
110     * Returns if store will clean up persisted files when shutdown (destroy()).
111     *
112     * @return
113     */

114    public boolean getPurgeOnShutdown()
115    {
116       return purgeOnShutdown;
117    }
118
119    /**
120     * This is a no op method, but needed in order to be used as a service within JBoss AS.
121     *
122     * @throws Exception
123     */

124    public void create() throws Exception JavaDoc
125    {
126    }
127
128    /**
129     * This will allow for change of file suffix and file path and then may start again
130     * using these new values. However, any object already written out using the old
131     * values will be lost as will not longer be accessible if these attributes are changed while stopped.
132     */

133    public void stop()
134    {
135       isStarted = false;
136    }
137
138    /**
139     * If purgeOnDestroy is true, will remove files upon shutdown.
140     */

141    public void destroy()
142    {
143       if(purgeOnShutdown)
144       {
145          purgeFiles();
146       }
147    }
148
149    public void purgeFiles()
150    {
151       String JavaDoc[] fileList = getObjectFileList();
152       String JavaDoc fileToDelete = null;
153       for(int x = 0; x < fileList.length; x++)
154       {
155          try
156          {
157             fileToDelete = filePath + System.getProperty("file.separator") + fileList[x];
158             File JavaDoc currentFile = new File JavaDoc(fileToDelete);
159             boolean deleted = currentFile.delete();
160             if(!deleted)
161             {
162                log.warn("Error purging file " + fileToDelete);
163             }
164          }
165          catch(Exception JavaDoc e)
166          {
167             log.warn("Error purging file " + fileToDelete);
168          }
169       }
170    }
171
172    /**
173     * Will use the values in the map to set configuration. This will not change behaviour of store until
174     * has been stopped and then started (if has not been started, will take effect upon start).
175     * The keys for the map are FILE_PATH_KEY and FILE_SUFFIX_KEY.
176     *
177     * @param config
178     */

179    public void setConfig(Map JavaDoc config)
180    {
181       if(config != null)
182       {
183          String JavaDoc newFilePath = (String JavaDoc) config.get(FILE_PATH_KEY);
184          if(newFilePath != null)
185          {
186             filePath = newFilePath;
187          }
188          String JavaDoc newFileSuffix = (String JavaDoc) config.get(FILE_SUFFIX_KEY);
189          if(newFileSuffix != null)
190          {
191             fileSuffix = newFileSuffix;
192          }
193       }
194    }
195
196    /**
197     * Gets the file path for the directory where the objects will be stored.
198     *
199     * @return
200     */

201    public String JavaDoc getStoreFilePath()
202    {
203       return filePath;
204    }
205
206    /**
207     * Sets teh file path for the directory where the objects will be stored.
208     *
209     * @param filePath
210     */

211    public void setStoreFilePath(String JavaDoc filePath)
212    {
213       this.filePath = filePath;
214    }
215
216    /**
217     * Gets the file suffix for each of the files that objects will be persisted to.
218     *
219     * @return
220     */

221    public String JavaDoc getStoreFileSuffix()
222    {
223       return fileSuffix;
224    }
225
226    /**
227     * Sets the file suffix for each of the files that objects will be persisted to.
228     *
229     * @param fileSuffix
230     */

231    public void setStoreFileSuffix(String JavaDoc fileSuffix)
232    {
233       this.fileSuffix = fileSuffix;
234    }
235
236
237    /**
238     * Getst the number of objects stored and available.
239     *
240     * @return
241     */

242    public int size()
243    {
244       verifyStarted();
245       String JavaDoc[] objectFileList = getObjectFileList();
246       if(objectFileList != null)
247       {
248          return objectFileList.length;
249       }
250       else
251       {
252          return 0;
253       }
254    }
255
256    private void verifyStarted()
257    {
258       if(!isStarted)
259       {
260          throw new RuntimeException JavaDoc("Can not call upon this store method before it has been started.");
261       }
262    }
263
264    /**
265     * Will look through the files in the store directory for the oldest object serialized to disk, load it,
266     * delete the file, and return the deserialized object.
267     * Important to note that once this object is returned from this method, it is gone forever from this
268     * store and will not be able to retrieve it again without adding it back.
269     *
270     * @return
271     * @throws IOException
272     */

273    public Object JavaDoc getNext() throws IOException JavaDoc
274    {
275       verifyStarted();
276
277       Object JavaDoc obj = null;
278       String JavaDoc objectFilePath = null;
279
280       synchronized(filePath)
281       {
282          String JavaDoc[] objectFileList = getObjectFileList();
283          FileInputStream JavaDoc inFile = null;
284          ObjectInputStream JavaDoc in = null;
285
286          if(objectFileList != null && objectFileList.length > 0)
287          {
288             try
289             {
290                // only getting the first one, which will be first one entered since the getting
291
// of the list is automatically ordered by the OS and all file names are numeric by time.
292
objectFilePath = filePath + System.getProperty("file.separator") + objectFileList[0];
293                inFile = new FileInputStream JavaDoc(objectFilePath);
294                in = new ObjectInputStream JavaDoc(inFile);
295                try
296                {
297                   obj = in.readObject();
298                }
299                catch(ClassNotFoundException JavaDoc e)
300                {
301                   throw new IOException JavaDoc("Error loading persisted object. Could not load class (" + e.getMessage() + ").");
302                }
303             }
304             finally
305             {
306                if(inFile != null)
307                {
308                   try
309                   {
310                      inFile.close();
311                   }
312                   catch(IOException JavaDoc ioe)
313                   {
314                      log.debug("Error closing FileInputStream.", ioe);
315                   }
316                }
317                if(in != null)
318                {
319                   try
320                   {
321                      in.close();
322                   }
323                   catch(IOException JavaDoc ioe)
324                   {
325                      log.debug("Error closing ObjectInputStream.", ioe);
326                   }
327                }
328             }
329          }
330       }
331
332       if(objectFilePath != null)
333       {
334          // now remove the file
335
File JavaDoc objectFile = new File JavaDoc(objectFilePath);
336          boolean isDeleted = objectFile.delete();
337          if(log.isTraceEnabled())
338          {
339             log.trace("object file (" + objectFilePath + ") has been deleted - " + isDeleted);
340          }
341       }
342
343       return obj;
344    }
345
346    private String JavaDoc[] getObjectFileList()
347    {
348       File JavaDoc storePath = new File JavaDoc(filePath);
349       String JavaDoc[] objectFileList = storePath.list(new StoreFileFilter());
350       return objectFileList;
351    }
352
353    /**
354     * Persists the serializable object passed to the directory specified. The file name will be the current time
355     * in milliseconds (vis System.currentTimeMillis()) with the specified suffix. This object can later be
356     * retrieved using the getNext() method, but objects will be returned in the order that they were added (FIFO).
357     *
358     * @param object
359     * @throws IOException
360     */

361    public void add(Serializable JavaDoc object) throws IOException JavaDoc
362    {
363       verifyStarted();
364
365       synchronized(filePath)
366       {
367          long currentTimestamp = System.currentTimeMillis();
368          File JavaDoc storeFile = new File JavaDoc(filePath + System.getProperty("file.separator") + String.valueOf(currentTimestamp) + "." + fileSuffix);
369          FileOutputStream JavaDoc outFile = null;
370          ObjectOutputStream JavaDoc out = null;
371
372          try
373          {
374             outFile = new FileOutputStream JavaDoc(storeFile, false);
375             out = new ObjectOutputStream JavaDoc(outFile);
376             out.writeObject(object);
377             out.flush();
378          }
379          finally
380          {
381             if(outFile != null)
382             {
383                try
384                {
385                   outFile.close();
386                }
387                catch(IOException JavaDoc ioe)
388                {
389                   log.debug("Error closing FileInputStream.", ioe);
390                }
391             }
392             if(out != null)
393             {
394                try
395                {
396                   out.close();
397                }
398                catch(IOException JavaDoc ioe)
399                {
400                   log.debug("Error closing ObjectInputStream.", ioe);
401                }
402             }
403
404          }
405       }
406    }
407
408    public class StoreFileFilter implements FilenameFilter JavaDoc
409    {
410       /**
411        * Tests if a specified file should be included in a file list.
412        *
413        * @param dir the directory in which the file was found.
414        * @param name the name of the file.
415        * @return <code>true</code> if and only if the name should be included in the file list; <code>false</code>
416        * otherwise.
417        */

418       public boolean accept(File JavaDoc dir, String JavaDoc name)
419       {
420          if(name.endsWith(fileSuffix))
421          {
422             return true;
423          }
424          else
425          {
426             return false;
427          }
428       }
429    }
430
431 }
432
Popular Tags