1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.vfs.cache;
18
19 import java.util.HashMap;
20 import java.util.Map;
21
22 import org.apache.commons.collections.map.AbstractLinkedMap;
23 import org.apache.commons.collections.map.LRUMap;
24 import org.apache.commons.logging.Log;
25 import org.apache.commons.logging.LogFactory;
26 import org.apache.commons.vfs.FileName;
27 import org.apache.commons.vfs.FileObject;
28 import org.apache.commons.vfs.FileSystem;
29 import org.apache.commons.vfs.FileSystemException;
30 import org.apache.commons.vfs.VfsLog;
31 import org.apache.commons.vfs.util.Messages;
32
33 /***
34 * This implementation caches every file using {@link LRUMap}.<br>
35 * The default constructor uses a LRU size of 100 per filesystem.
36 *
37 * @author <a href="mailto:imario@apache.org">Mario Ivankovits</a>
38 * @version $Revision: 480428 $ $Date: 2006-11-29 07:15:24 +0100 (Mi, 29 Nov 2006) $
39 */
40 public class LRUFilesCache extends AbstractFilesCache
41 {
42 /***
43 * The logger to use.
44 */
45 private Log log = LogFactory.getLog(LRUFilesCache.class);
46
47 private final Map filesystemCache = new HashMap(10);
48 private final int lruSize;
49
50 private class MyLRUMap extends LRUMap
51 {
52 final FileSystem filesystem;
53
54 public MyLRUMap(final FileSystem filesystem, int size)
55 {
56 super(size, true);
57 this.filesystem = filesystem;
58 }
59
60 protected boolean removeLRU(final AbstractLinkedMap.LinkEntry linkEntry)
61 {
62 synchronized (LRUFilesCache.this)
63 {
64 FileObject file = (FileObject) linkEntry.getValue();
65
66
67
68 if (file.isAttached() || file.isContentOpen())
69 {
70
71
72 return false;
73 }
74
75
76 if (super.removeLRU(linkEntry))
77 {
78 try
79 {
80
81 file.close();
82 }
83 catch (FileSystemException e)
84 {
85 VfsLog.warn(getLogger(), log, Messages.getString("vfs.impl/LRUFilesCache-remove-ex.warn"), e);
86 }
87
88 Map files = (Map) filesystemCache.get(filesystem);
89 if (files.size() < 1)
90 {
91 filesystemCache.remove(filesystem);
92 }
93
94 return true;
95 }
96
97 return false;
98 }
99 }
100 }
101
102 /***
103 * Default constructor. Uses a LRU size of 100 per filesystem.
104 */
105 public LRUFilesCache()
106 {
107 this(100);
108 }
109
110 /***
111 * Set the desired LRU size.
112 *
113 * @param lruSize the LRU size
114 */
115 public LRUFilesCache(int lruSize)
116 {
117 this.lruSize = lruSize;
118 }
119
120 public void putFile(final FileObject file)
121 {
122 synchronized (this)
123 {
124 Map files = getOrCreateFilesystemCache(file.getFileSystem());
125
126
127
128 files.put(file.getName(), file);
129 }
130 }
131
132 public FileObject getFile(final FileSystem filesystem, final FileName name)
133 {
134 synchronized (this)
135 {
136 Map files = getOrCreateFilesystemCache(filesystem);
137
138
139
140
141 return (FileObject) files.get(name);
142 }
143 }
144
145 public void clear(final FileSystem filesystem)
146 {
147 synchronized (this)
148 {
149
150
151 Map files = getOrCreateFilesystemCache(filesystem);
152 files.clear();
153
154 filesystemCache.remove(filesystem);
155 }
156 }
157
158 protected Map getOrCreateFilesystemCache(final FileSystem filesystem)
159 {
160 Map files = (Map) filesystemCache.get(filesystem);
161 if (files == null)
162 {
163
164
165 files = new MyLRUMap(filesystem, lruSize);
166 filesystemCache.put(filesystem, files);
167 }
168
169 return files;
170 }
171
172 public void close()
173 {
174 super.close();
175
176 synchronized (this)
177 {
178
179
180 filesystemCache.clear();
181 }
182 }
183
184 public void removeFile(final FileSystem filesystem, final FileName name)
185 {
186 synchronized (this)
187 {
188 Map files = getOrCreateFilesystemCache(filesystem);
189
190
191
192 files.remove(name);
193
194 if (files.size() < 1)
195 {
196 filesystemCache.remove(filesystem);
197 }
198 }
199 }
200
201 public void touchFile(final FileObject file)
202 {
203
204 getFile(file.getFileSystem(), file.getName());
205 }
206 }