KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > vfs > cache > SoftRefFilesCache


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

16 package org.apache.commons.vfs.cache;
17
18 import java.lang.ref.Reference JavaDoc;
19 import java.lang.ref.ReferenceQueue JavaDoc;
20 import java.lang.ref.SoftReference JavaDoc;
21 import java.util.HashMap JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.Map JavaDoc;
24 import java.util.TreeMap JavaDoc;
25
26 import org.apache.commons.logging.Log;
27 import org.apache.commons.logging.LogFactory;
28 import org.apache.commons.vfs.FileName;
29 import org.apache.commons.vfs.FileObject;
30 import org.apache.commons.vfs.FileSystem;
31 import org.apache.commons.vfs.VfsLog;
32 import org.apache.commons.vfs.impl.DefaultFileSystemManager;
33 import org.apache.commons.vfs.util.Messages;
34
35 /**
36  * This implementation caches every file as long as it is strongly reachable by
37  * the java vm. As soon as the vm needs memory - every softly reachable file
38  * will be discarded.
39  *
40  * @author <a HREF="mailto:imario@apache.org">Mario Ivankovits</a>
41  * @see SoftReference
42  */

43 public class SoftRefFilesCache extends AbstractFilesCache
44 {
45     /**
46      * The logger to use.
47      */

48     private Log log = LogFactory.getLog(SoftRefFilesCache.class);
49
50     private final Map JavaDoc filesystemCache = new HashMap JavaDoc();
51     private final Map JavaDoc refReverseMap = new HashMap JavaDoc(100);
52     private final ReferenceQueue JavaDoc refqueue = new ReferenceQueue JavaDoc();
53
54     private SoftRefReleaseThread softRefReleaseThread = null;
55
56     /**
57      * This thread will listen on the ReferenceQueue and remove the entry in the
58      * filescache as soon as the vm removes the reference
59      */

60     private class SoftRefReleaseThread extends Thread JavaDoc
61     {
62         private boolean requestEnd = false;
63
64         private SoftRefReleaseThread()
65         {
66             setName(SoftRefReleaseThread.class.getName());
67             setDaemon(true);
68         }
69
70         public void run()
71         {
72             loop: while (!requestEnd && !Thread.currentThread().isInterrupted())
73             {
74                 try
75                 {
76                     Reference JavaDoc ref = refqueue.remove(1000);
77                     if (ref == null)
78                     {
79                         continue;
80                     }
81
82                     FileSystemAndNameKey key = (FileSystemAndNameKey) refReverseMap
83                             .get(ref);
84
85                     if (key != null)
86                     {
87                         if (removeFile(key))
88                         {
89                             filesystemClose(key.getFileSystem());
90                         }
91                     }
92                 }
93                 catch (InterruptedException JavaDoc e)
94                 {
95                     if (!requestEnd)
96                     {
97                         VfsLog
98                                 .warn(
99                                         getLogger(),
100                                         log,
101                                         Messages
102                                                 .getString("vfs.impl/SoftRefReleaseThread-interrupt.info"));
103                     }
104                     break loop;
105                 }
106             }
107         }
108     }
109
110     public SoftRefFilesCache()
111     {
112     }
113
114     private void startThread()
115     {
116         if (softRefReleaseThread != null)
117         {
118             throw new IllegalStateException JavaDoc(
119                     Messages
120                             .getString("vfs.impl/SoftRefReleaseThread-already-running.warn"));
121         }
122
123         softRefReleaseThread = new SoftRefReleaseThread();
124         softRefReleaseThread.start();
125     }
126
127     private void endThread()
128     {
129         if (softRefReleaseThread != null)
130         {
131             softRefReleaseThread.requestEnd = true;
132             softRefReleaseThread.interrupt();
133             softRefReleaseThread = null;
134         }
135     }
136
137     public void putFile(final FileObject file)
138     {
139         if (log.isDebugEnabled())
140         {
141             log.debug("putFile: " + file.getName());
142         }
143
144         Map JavaDoc files = getOrCreateFilesystemCache(file.getFileSystem());
145
146         Reference JavaDoc ref = new SoftReference JavaDoc(file, refqueue);
147         FileSystemAndNameKey key = new FileSystemAndNameKey(file
148                 .getFileSystem(), file.getName());
149
150         synchronized (files)
151         {
152             files.put(file.getName(), ref);
153             refReverseMap.put(ref, key);
154         }
155     }
156
157     public FileObject getFile(final FileSystem filesystem, final FileName name)
158     {
159         Map JavaDoc files = getOrCreateFilesystemCache(filesystem);
160
161         synchronized (files)
162         {
163             SoftReference JavaDoc ref = (SoftReference JavaDoc) files.get(name);
164             if (ref == null)
165             {
166                 return null;
167             }
168
169             FileObject fo = (FileObject) ref.get();
170             if (fo == null)
171             {
172                 removeFile(filesystem, name);
173             }
174             return fo;
175         }
176     }
177
178     public void clear(FileSystem filesystem)
179     {
180         Map JavaDoc files = getOrCreateFilesystemCache(filesystem);
181
182         boolean closeFilesystem;
183
184         synchronized (files)
185         {
186             Iterator JavaDoc iterKeys = refReverseMap.values().iterator();
187             while (iterKeys.hasNext())
188             {
189                 FileSystemAndNameKey key = (FileSystemAndNameKey) iterKeys
190                         .next();
191                 if (key.getFileSystem() == filesystem)
192                 {
193                     iterKeys.remove();
194                     files.remove(key.getFileName());
195                 }
196             }
197
198             closeFilesystem = files.size() < 1;
199         }
200
201         if (closeFilesystem)
202         {
203             filesystemClose(filesystem);
204         }
205     }
206
207     private void filesystemClose(FileSystem filesystem)
208     {
209         if (log.isDebugEnabled())
210         {
211             log.debug("close fs: " + filesystem.getRootName());
212         }
213         synchronized (filesystemCache)
214         {
215             filesystemCache.remove(filesystem);
216             if (filesystemCache.size() < 1)
217             {
218                 endThread();
219             }
220         }
221         ((DefaultFileSystemManager) getContext().getFileSystemManager())
222                 .closeFileSystem(filesystem);
223     }
224
225     public void close()
226     {
227         super.close();
228
229         endThread();
230
231         // files.clear();
232
synchronized (filesystemCache)
233         {
234             filesystemCache.clear();
235         }
236         refReverseMap.clear();
237     }
238
239     public void removeFile(FileSystem filesystem, FileName name)
240     {
241         if (removeFile(new FileSystemAndNameKey(filesystem, name)))
242         {
243             filesystemClose(filesystem);
244         }
245     }
246
247     public void touchFile(FileObject file)
248     {
249     }
250
251     private boolean removeFile(final FileSystemAndNameKey key)
252     {
253         if (log.isDebugEnabled())
254         {
255             log.debug("removeFile: " + key.getFileName());
256         }
257
258         Map JavaDoc files = getOrCreateFilesystemCache(key.getFileSystem());
259
260         synchronized (files)
261         {
262             Object JavaDoc ref = files.remove(key.getFileName());
263             if (ref != null)
264             {
265                 refReverseMap.remove(ref);
266             }
267
268             return files.size() < 1;
269         }
270     }
271
272     protected Map JavaDoc getOrCreateFilesystemCache(final FileSystem filesystem)
273     {
274         synchronized (filesystemCache)
275         {
276             if (filesystemCache.size() < 1)
277             {
278                 startThread();
279             }
280
281             Map JavaDoc files = (Map JavaDoc) filesystemCache.get(filesystem);
282             if (files == null)
283             {
284                 files = new TreeMap JavaDoc();
285                 filesystemCache.put(filesystem, files);
286             }
287
288             return files;
289         }
290     }
291 }
292
Popular Tags