KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > catalina > session > FileStore


1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18
19 package org.apache.catalina.session;
20
21
22 import java.io.BufferedInputStream JavaDoc;
23 import java.io.BufferedOutputStream JavaDoc;
24 import java.io.File JavaDoc;
25 import java.io.FileInputStream JavaDoc;
26 import java.io.FileNotFoundException JavaDoc;
27 import java.io.FileOutputStream JavaDoc;
28 import java.io.IOException JavaDoc;
29 import java.io.ObjectInputStream JavaDoc;
30 import java.io.ObjectOutputStream JavaDoc;
31 import java.util.ArrayList JavaDoc;
32
33 import javax.servlet.ServletContext JavaDoc;
34
35 import org.apache.catalina.Container;
36 import org.apache.catalina.Context;
37 import org.apache.catalina.Globals;
38 import org.apache.catalina.Loader;
39 import org.apache.catalina.Session;
40 import org.apache.catalina.Store;
41 import org.apache.catalina.util.CustomObjectInputStream;
42
43
44 /**
45  * Concrete implementation of the <b>Store</b> interface that utilizes
46  * a file per saved Session in a configured directory. Sessions that are
47  * saved are still subject to being expired based on inactivity.
48  *
49  * @author Craig R. McClanahan
50  * @version $Revision: 467222 $ $Date: 2006-10-24 05:17:11 +0200 (mar., 24 oct. 2006) $
51  */

52
53 public final class FileStore
54     extends StoreBase implements Store {
55
56
57     // ----------------------------------------------------- Constants
58

59
60     /**
61      * The extension to use for serialized session filenames.
62      */

63     private static final String JavaDoc FILE_EXT = ".session";
64
65
66     // ----------------------------------------------------- Instance Variables
67

68
69     /**
70      * The pathname of the directory in which Sessions are stored.
71      * This may be an absolute pathname, or a relative path that is
72      * resolved against the temporary work directory for this application.
73      */

74     private String JavaDoc directory = ".";
75
76
77     /**
78      * A File representing the directory in which Sessions are stored.
79      */

80     private File JavaDoc directoryFile = null;
81
82
83     /**
84      * The descriptive information about this implementation.
85      */

86     private static final String JavaDoc info = "FileStore/1.0";
87
88     /**
89      * Name to register for this Store, used for logging.
90      */

91     private static final String JavaDoc storeName = "fileStore";
92
93     /**
94      * Name to register for the background thread.
95      */

96     private static final String JavaDoc threadName = "FileStore";
97
98
99     // ------------------------------------------------------------- Properties
100

101
102     /**
103      * Return the directory path for this Store.
104      */

105     public String JavaDoc getDirectory() {
106
107         return (directory);
108
109     }
110
111
112     /**
113      * Set the directory path for this Store.
114      *
115      * @param path The new directory path
116      */

117     public void setDirectory(String JavaDoc path) {
118
119         String JavaDoc oldDirectory = this.directory;
120         this.directory = path;
121         this.directoryFile = null;
122         support.firePropertyChange("directory", oldDirectory,
123                                    this.directory);
124
125     }
126
127
128     /**
129      * Return descriptive information about this Store implementation and
130      * the corresponding version number, in the format
131      * <code>&lt;description&gt;/&lt;version&gt;</code>.
132      */

133     public String JavaDoc getInfo() {
134
135         return (info);
136
137     }
138
139     /**
140      * Return the thread name for this Store.
141      */

142     public String JavaDoc getThreadName() {
143         return(threadName);
144     }
145
146     /**
147      * Return the name for this Store, used for logging.
148      */

149     public String JavaDoc getStoreName() {
150         return(storeName);
151     }
152
153
154     /**
155      * Return the number of Sessions present in this Store.
156      *
157      * @exception IOException if an input/output error occurs
158      */

159     public int getSize() throws IOException JavaDoc {
160
161         // Acquire the list of files in our storage directory
162
File JavaDoc file = directory();
163         if (file == null) {
164             return (0);
165         }
166         String JavaDoc files[] = file.list();
167
168         // Figure out which files are sessions
169
int keycount = 0;
170         for (int i = 0; i < files.length; i++) {
171             if (files[i].endsWith(FILE_EXT)) {
172                 keycount++;
173             }
174         }
175         return (keycount);
176
177     }
178
179
180     // --------------------------------------------------------- Public Methods
181

182
183     /**
184      * Remove all of the Sessions in this Store.
185      *
186      * @exception IOException if an input/output error occurs
187      */

188     public void clear()
189         throws IOException JavaDoc {
190
191         String JavaDoc[] keys = keys();
192         for (int i = 0; i < keys.length; i++) {
193             remove(keys[i]);
194         }
195
196     }
197
198
199     /**
200      * Return an array containing the session identifiers of all Sessions
201      * currently saved in this Store. If there are no such Sessions, a
202      * zero-length array is returned.
203      *
204      * @exception IOException if an input/output error occurred
205      */

206     public String JavaDoc[] keys() throws IOException JavaDoc {
207
208         // Acquire the list of files in our storage directory
209
File JavaDoc file = directory();
210         if (file == null) {
211             return (new String JavaDoc[0]);
212         }
213
214         String JavaDoc files[] = file.list();
215         
216         // Bugzilla 32130
217
if((files == null) || (files.length < 1)) {
218             return (new String JavaDoc[0]);
219         }
220
221         // Build and return the list of session identifiers
222
ArrayList JavaDoc list = new ArrayList JavaDoc();
223         int n = FILE_EXT.length();
224         for (int i = 0; i < files.length; i++) {
225             if (files[i].endsWith(FILE_EXT)) {
226                 list.add(files[i].substring(0, files[i].length() - n));
227             }
228         }
229         return ((String JavaDoc[]) list.toArray(new String JavaDoc[list.size()]));
230
231     }
232
233
234     /**
235      * Load and return the Session associated with the specified session
236      * identifier from this Store, without removing it. If there is no
237      * such stored Session, return <code>null</code>.
238      *
239      * @param id Session identifier of the session to load
240      *
241      * @exception ClassNotFoundException if a deserialization error occurs
242      * @exception IOException if an input/output error occurs
243      */

244     public Session load(String JavaDoc id)
245         throws ClassNotFoundException JavaDoc, IOException JavaDoc {
246
247         // Open an input stream to the specified pathname, if any
248
File JavaDoc file = file(id);
249         if (file == null) {
250             return (null);
251         }
252
253         if (! file.exists()) {
254             return (null);
255         }
256         if (manager.getContainer().getLogger().isDebugEnabled()) {
257             manager.getContainer().getLogger().debug(sm.getString(getStoreName()+".loading",
258                              id, file.getAbsolutePath()));
259         }
260
261         FileInputStream JavaDoc fis = null;
262         ObjectInputStream JavaDoc ois = null;
263         Loader loader = null;
264         ClassLoader JavaDoc classLoader = null;
265         try {
266             fis = new FileInputStream JavaDoc(file.getAbsolutePath());
267             BufferedInputStream JavaDoc bis = new BufferedInputStream JavaDoc(fis);
268             Container container = manager.getContainer();
269             if (container != null)
270                 loader = container.getLoader();
271             if (loader != null)
272                 classLoader = loader.getClassLoader();
273             if (classLoader != null)
274                 ois = new CustomObjectInputStream(bis, classLoader);
275             else
276                 ois = new ObjectInputStream JavaDoc(bis);
277         } catch (FileNotFoundException JavaDoc e) {
278             if (manager.getContainer().getLogger().isDebugEnabled())
279                 manager.getContainer().getLogger().debug("No persisted data file found");
280             return (null);
281         } catch (IOException JavaDoc e) {
282             if (ois != null) {
283                 try {
284                     ois.close();
285                 } catch (IOException JavaDoc f) {
286                     ;
287                 }
288                 ois = null;
289             }
290             throw e;
291         }
292
293         try {
294             StandardSession session =
295                 (StandardSession) manager.createEmptySession();
296             session.readObjectData(ois);
297             session.setManager(manager);
298             return (session);
299         } finally {
300             // Close the input stream
301
if (ois != null) {
302                 try {
303                     ois.close();
304                 } catch (IOException JavaDoc f) {
305                     ;
306                 }
307             }
308         }
309     }
310
311
312     /**
313      * Remove the Session with the specified session identifier from
314      * this Store, if present. If no such Session is present, this method
315      * takes no action.
316      *
317      * @param id Session identifier of the Session to be removed
318      *
319      * @exception IOException if an input/output error occurs
320      */

321     public void remove(String JavaDoc id) throws IOException JavaDoc {
322
323         File JavaDoc file = file(id);
324         if (file == null) {
325             return;
326         }
327         if (manager.getContainer().getLogger().isDebugEnabled()) {
328             manager.getContainer().getLogger().debug(sm.getString(getStoreName()+".removing",
329                              id, file.getAbsolutePath()));
330         }
331         file.delete();
332
333     }
334
335
336     /**
337      * Save the specified Session into this Store. Any previously saved
338      * information for the associated session identifier is replaced.
339      *
340      * @param session Session to be saved
341      *
342      * @exception IOException if an input/output error occurs
343      */

344     public void save(Session session) throws IOException JavaDoc {
345
346         // Open an output stream to the specified pathname, if any
347
File JavaDoc file = file(session.getIdInternal());
348         if (file == null) {
349             return;
350         }
351         if (manager.getContainer().getLogger().isDebugEnabled()) {
352             manager.getContainer().getLogger().debug(sm.getString(getStoreName()+".saving",
353                              session.getIdInternal(), file.getAbsolutePath()));
354         }
355         FileOutputStream JavaDoc fos = null;
356         ObjectOutputStream JavaDoc oos = null;
357         try {
358             fos = new FileOutputStream JavaDoc(file.getAbsolutePath());
359             oos = new ObjectOutputStream JavaDoc(new BufferedOutputStream JavaDoc(fos));
360         } catch (IOException JavaDoc e) {
361             if (oos != null) {
362                 try {
363                     oos.close();
364                 } catch (IOException JavaDoc f) {
365                     ;
366                 }
367             }
368             throw e;
369         }
370
371         try {
372             ((StandardSession)session).writeObjectData(oos);
373         } finally {
374             oos.close();
375         }
376
377     }
378
379
380     // -------------------------------------------------------- Private Methods
381

382
383     /**
384      * Return a File object representing the pathname to our
385      * session persistence directory, if any. The directory will be
386      * created if it does not already exist.
387      */

388     private File JavaDoc directory() {
389
390         if (this.directory == null) {
391             return (null);
392         }
393         if (this.directoryFile != null) {
394             // NOTE: Race condition is harmless, so do not synchronize
395
return (this.directoryFile);
396         }
397         File JavaDoc file = new File JavaDoc(this.directory);
398         if (!file.isAbsolute()) {
399             Container container = manager.getContainer();
400             if (container instanceof Context JavaDoc) {
401                 ServletContext JavaDoc servletContext =
402                     ((Context JavaDoc) container).getServletContext();
403                 File JavaDoc work = (File JavaDoc)
404                     servletContext.getAttribute(Globals.WORK_DIR_ATTR);
405                 file = new File JavaDoc(work, this.directory);
406             } else {
407                 throw new IllegalArgumentException JavaDoc
408                     ("Parent Container is not a Context");
409             }
410         }
411         if (!file.exists() || !file.isDirectory()) {
412             file.delete();
413             file.mkdirs();
414         }
415         this.directoryFile = file;
416         return (file);
417
418     }
419
420
421     /**
422      * Return a File object representing the pathname to our
423      * session persistence file, if any.
424      *
425      * @param id The ID of the Session to be retrieved. This is
426      * used in the file naming.
427      */

428     private File JavaDoc file(String JavaDoc id) {
429
430         if (this.directory == null) {
431             return (null);
432         }
433         String JavaDoc filename = id + FILE_EXT;
434         File JavaDoc file = new File JavaDoc(directory(), filename);
435         return (file);
436
437     }
438
439
440 }
441
Popular Tags