1 16 package org.apache.commons.vfs.cache; 17 18 import java.lang.ref.Reference ; 19 import java.lang.ref.ReferenceQueue ; 20 import java.lang.ref.SoftReference ; 21 import java.util.HashMap ; 22 import java.util.Iterator ; 23 import java.util.Map ; 24 import java.util.TreeMap ; 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 43 public class SoftRefFilesCache extends AbstractFilesCache 44 { 45 48 private Log log = LogFactory.getLog(SoftRefFilesCache.class); 49 50 private final Map filesystemCache = new HashMap (); 51 private final Map refReverseMap = new HashMap (100); 52 private final ReferenceQueue refqueue = new ReferenceQueue (); 53 54 private SoftRefReleaseThread softRefReleaseThread = null; 55 56 60 private class SoftRefReleaseThread extends Thread 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 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 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 ( 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 files = getOrCreateFilesystemCache(file.getFileSystem()); 145 146 Reference ref = new SoftReference (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 files = getOrCreateFilesystemCache(filesystem); 160 161 synchronized (files) 162 { 163 SoftReference ref = (SoftReference ) 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 files = getOrCreateFilesystemCache(filesystem); 181 182 boolean closeFilesystem; 183 184 synchronized (files) 185 { 186 Iterator 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 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 files = getOrCreateFilesystemCache(key.getFileSystem()); 259 260 synchronized (files) 261 { 262 Object 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 getOrCreateFilesystemCache(final FileSystem filesystem) 273 { 274 synchronized (filesystemCache) 275 { 276 if (filesystemCache.size() < 1) 277 { 278 startThread(); 279 } 280 281 Map files = (Map ) filesystemCache.get(filesystem); 282 if (files == null) 283 { 284 files = new TreeMap (); 285 filesystemCache.put(filesystem, files); 286 } 287 288 return files; 289 } 290 } 291 } 292 | Popular Tags |