1 19 20 package org.netbeans.modules.masterfs.filebasedfs.fileobjects; 21 22 import java.io.FileNotFoundException ; 23 import java.lang.ref.WeakReference ; 24 import java.util.Collections ; 25 import java.util.Iterator ; 26 import org.netbeans.modules.masterfs.filebasedfs.utils.FSException; 27 import org.openide.filesystems.FileLock; 28 29 import java.io.File ; 30 import java.io.IOException ; 31 import java.io.RandomAccessFile ; 32 import java.lang.ref.Reference ; 33 import java.nio.channels.FileChannel ; 34 import java.util.ArrayList ; 35 import java.util.List ; 36 import java.util.Map ; 37 import java.util.Set ; 38 import java.util.Stack ; 39 import java.util.WeakHashMap ; 40 import org.openide.filesystems.FileAlreadyLockedException; 41 import org.openide.util.Exceptions; 42 import org.openide.util.NbBundle; 43 44 45 66 67 68 public class WriteLock extends FileLock { 69 static final Map allLocks = Collections.synchronizedMap(new WeakHashMap ()); 70 private File lockFile; 71 72 static { 73 Runtime.getRuntime().addShutdownHook(new Thread () { 74 public void run() { 75 Set s = allLocks.keySet(); 76 synchronized(allLocks) { 77 for (Iterator it = s.iterator(); it.hasNext();) { 78 File f = (File ) it.next(); 79 if (f.exists() && WriteLockUtils.hasActiveLockFileSigns(f.getAbsolutePath())) { 80 f.delete(); 81 } 82 } 83 } 84 } 85 }); 86 } 87 88 static WriteLock tryLock(final File file) throws IOException { 89 return WriteLock.getInstance(file, false); 90 } 91 92 static WriteLock tryNioLock(final File file) throws IOException { 93 return WriteLock.getInstance(file, true); 94 } 95 96 static WriteLock tryLightWeightLock(final File file) throws IOException { 97 return WriteLock.getLightWeightInstance(file); 98 } 99 100 public static void relock(final File theOld, File theNew) { 101 List l = new ArrayList (); 102 Set s = allLocks.keySet(); 103 synchronized(allLocks) { 104 for (Iterator it = s.iterator(); it.hasNext();) { 105 File f = (File ) it.next(); 106 File nLockFile = null; 107 String relPath = getRelativePath(theOld, f); 108 if (relPath != null) { 109 nLockFile = new File (theNew, relPath); 110 } else if (f.equals(WriteLockUtils.getAssociatedLockFile(theOld))) { 111 nLockFile = WriteLockUtils.getAssociatedLockFile(theNew); 112 } 113 114 if (nLockFile != null) { 115 Reference r = (Reference )allLocks.get(f); 116 WriteLock wl = (WriteLock)r.get(); 117 if (wl != null) { 118 it.remove(); 119 wl.lockFile = nLockFile; 120 l.add(wl); 121 } 122 123 } 124 } 125 } 126 for (Iterator it2 = l.iterator(); it2.hasNext();) { 127 WriteLock wl = (WriteLock) it2.next(); 128 allLocks.put(wl.lockFile, new WeakReference (wl)); 129 } 130 } 131 132 private static String getRelativePath(final File dir, final File file) { 133 Stack stack = new Stack (); 134 File tempFile = file; 135 while(tempFile != null && !tempFile.equals(dir)) { 136 stack.push (tempFile.getName()); 137 tempFile = tempFile.getParentFile(); 138 } 139 if (tempFile == null) return null; 140 StringBuilder retval = new StringBuilder (); 141 while (!stack.isEmpty()) { 142 retval.append((String )stack.pop()); 143 if (!stack.isEmpty()) { 144 retval.append("/"); } 146 } 147 return retval.toString(); 148 } 149 150 151 private static WriteLock getLightWeightInstance(final File file) throws IOException { 152 File lckFile = WriteLockUtils.getAssociatedLockFile(file); 153 boolean isAlreadyLocked = WriteLock.allLocks.keySet().contains(lckFile); 154 if (isAlreadyLocked) { 155 throw new FileAlreadyLockedException(NbBundle.getMessage( 156 WriteLock.class, "EXC_FileAlreadyLocked", file.getAbsolutePath())); 157 } 158 159 return new WriteLock(lckFile); 160 } 161 162 private static WriteLock getInstance(final File file, boolean nioLock) throws IOException { 163 boolean isCreated = false; 164 IOException toFire = null; 165 166 File lckFile = WriteLockUtils.getAssociatedLockFile(file); 167 if (!lckFile.exists()) { 168 isCreated = true; 169 } 170 RandomAccessFile raf = getAccessToFile(lckFile); assert lckFile.exists(); 172 173 FileChannel channel = raf.getChannel(); 174 175 176 if (channel != null && channel.isOpen()) { 177 try { 178 String content = WriteLockUtils.getContentOfLckFile(lckFile, channel); 179 if (content == null && (isCreated || lckFile.length() == 0)) { 180 assert lckFile.length() == 0; 181 content = WriteLockUtils.writeContentOfLckFile(lckFile, channel); 182 } 183 184 if (content != null && !WriteLock.allLocks.keySet().contains(new File (content))) { 185 if (channel != null && channel.isOpen() && !nioLock) { 186 channel.close(); 187 } 188 return (nioLock) ? new NioLock(lckFile, channel, channel.tryLock()) : new WriteLock(lckFile); 189 } 190 } catch (IOException iex) { 191 toFire = iex; 192 } 193 } 194 195 if (channel != null && channel.isOpen()) { 196 channel.close(); 197 } 198 199 if (isCreated && lckFile.exists()) { 200 lckFile.delete(); 201 } 202 203 if (toFire == null) { 204 if (lckFile.exists()) { 205 toFire = new FileAlreadyLockedException(NbBundle.getMessage( 206 WriteLock.class, "EXC_FileLockAlreadyExists", file.getAbsolutePath(), lckFile.getAbsolutePath())); 207 } else { 208 toFire = new FileAlreadyLockedException(NbBundle.getMessage( 209 WriteLock.class, "EXC_FileAlreadyLocked", file.getAbsolutePath())); 210 } 211 } 212 213 FSException.annotateException(toFire); 214 throw toFire; 215 } 216 217 private static RandomAccessFile getAccessToFile(final File f) throws FileNotFoundException { 218 RandomAccessFile raf = null; 219 try { 220 raf = new RandomAccessFile (f, "rwd"); } catch (FileNotFoundException e) { 222 FileNotFoundException fex = e; 223 if (!f.exists()) { 224 fex = (FileNotFoundException )new FileNotFoundException (e.getLocalizedMessage()).initCause(e); 225 } else if (!f.canRead()) { 226 fex = (FileNotFoundException )new FileNotFoundException (e.getLocalizedMessage()).initCause(e); 227 } else if (!f.canWrite()) { 228 fex = (FileNotFoundException )new FileNotFoundException (e.getLocalizedMessage()).initCause(e); 229 } else if (f.getParentFile() == null) { 230 fex = (FileNotFoundException )new FileNotFoundException (e.getLocalizedMessage()).initCause(e); 231 } else if (!f.getParentFile().exists()) { 232 fex = (FileNotFoundException )new FileNotFoundException (e.getLocalizedMessage()).initCause(e); 233 } 234 throw fex; 235 } 236 return raf; 237 } 238 239 240 private WriteLock(File lockFile) { 241 this.lockFile = lockFile; 242 register(); 243 } 244 245 public boolean isValid(final File f) { 246 boolean retVal = isValid(); 247 248 if (retVal) { 249 final File associatedLockFile = WriteLockUtils.getAssociatedLockFile(f); 250 retVal = lockFile.equals(associatedLockFile); 251 } else { 252 } 253 return retVal; 254 } 255 256 public void releaseLock() { 257 synchronized (WriteLockFactory.class) { 258 if (isValid()) { 259 deregister(); 260 super.releaseLock(); 261 if (getLockFile().exists()) { 262 final boolean isDeleted = getLockFile().delete(); 263 } 265 } 266 } 267 } 268 269 private final void deregister() { 270 allLocks.remove(getLockFile()); 271 } 272 273 private final void register() { 274 allLocks.put(this.getLockFile(), new WeakReference (this)); 275 } 276 277 final File getLockFile() { 278 return lockFile; 279 } 280 281 public final String toString() { 282 final String name = getLockFile().getName(); 283 final String newName = name.substring(WriteLockUtils.PREFIX.length(), (name.length() - WriteLockUtils.SUFFIX.length())); 284 return new File (getLockFile().getParentFile(), newName).getAbsolutePath(); 285 } 286 287 private static class NioLock extends WriteLock { 288 private FileChannel channel; 289 private java.nio.channels.FileLock nioLock; 290 291 NioLock(File lockFile, FileChannel channel, java.nio.channels.FileLock nioLock) { 292 super(lockFile); 293 294 assert nioLock != null; 295 assert nioLock.isValid(); 296 assert channel != null; 297 298 this.channel = channel; 299 this.nioLock = nioLock; 300 } 301 302 public void releaseLock() { 303 synchronized (WriteLockFactory.class) { 304 try { 305 if (nioLock.isValid()) { 306 nioLock.release(); 307 } 308 309 if (channel.isOpen()) { 310 channel.close(); 311 } 312 } catch (java.io.IOException e) { 313 Exceptions.printStackTrace(e); 314 } 315 316 super.releaseLock(); 317 } 318 } 319 } 320 } 321 | Popular Tags |