1 19 20 package org.netbeans.modules.masterfs; 21 22 import java.io.IOException ; 23 import java.io.File ; 24 import java.lang.ref.Reference ; 25 import java.lang.ref.WeakReference ; 26 import java.util.Collection ; 27 import java.util.HashMap ; 28 import java.util.Iterator ; 29 import java.util.Map ; 30 import java.util.WeakHashMap ; 31 import org.netbeans.modules.masterfs.filebasedfs.fileobjects.WriteLock; 32 import org.netbeans.modules.masterfs.filebasedfs.fileobjects.WriteLockFactory; 33 import org.openide.filesystems.FileAlreadyLockedException; 34 import org.openide.filesystems.FileChangeListener; 35 import org.openide.filesystems.FileLock; 36 import org.openide.filesystems.FileObject; 37 import org.openide.filesystems.FileUtil; 38 import org.netbeans.modules.masterfs.filebasedfs.fileobjects.WriteLockUtils; 39 import org.openide.util.Exceptions; 40 import org.openide.util.WeakListeners; 41 42 45 final class Delegate { 46 private FileObject delegate; 47 private FileObject secondDelegate; 48 private FileChangeListener weakListener; 49 final private FileChangeListener fListener; 50 private Reference lock = null; 51 52 private int attribs = 0; 53 54 static final int SECOND_DELEGATE = 1; 55 static final int BEST_DELEGATE = 0; 56 private final MasterFileObject mfo; 57 58 Delegate(final FileObject fo, final FileChangeListener fListener, MasterFileObject mfo) { 59 this.fListener = fListener; 60 this.mfo = mfo; 61 } 62 63 FileObject get() { 64 ResourcePath resPath = mfo.getResource(); 65 FileObject retVal = delegate; 66 if (delegate instanceof InvalidDelegate) { 67 retVal = null; 68 } else { 69 if (retVal == null) { 70 retVal = resolve(resPath, true); 71 set(retVal); 72 } 73 } 74 return retVal; 75 } 76 77 FileObject get(boolean maybeInvalid) { 78 FileObject retVal = get (); 79 if (maybeInvalid && retVal == null) { 80 retVal = delegate; 81 } 82 return retVal; 83 } 84 85 static FileObject resolve(final ResourcePath resPath) { 86 return resolve(resPath, true); 87 } 88 89 private static FileObject resolve(final ResourcePath resPath, final boolean bestDelegate) { 90 FileObject retVal; 91 String normalizedPath = resPath.getNormalizedPath(); 92 if (WriteLockUtils.hasActiveLockFileSigns(normalizedPath)) { 93 File f = new ResourcePath(normalizedPath).getFile(); 94 if (WriteLockUtils.hasActiveLockFileSigns(f.getName())) { 95 return null; 96 } 97 } 98 99 if (bestDelegate) { 100 retVal = MountTable.getDefault().resolveBestDelegate(normalizedPath); 101 } else { 102 retVal = MountTable.getDefault().resolveSecondDelegate(normalizedPath); 103 } 104 105 if (retVal == null) { 106 retVal = SpecialDelegates.get(resPath); 107 } else { 108 retVal.getAttribute("--hack--"); } 112 return retVal; 113 } 114 115 static FileLock getLockForDelegate(final FileLock testedLock, final FileObject delegate) throws IOException { 116 if (testedLock == null) 117 throw new IOException (); 118 119 if (!(testedLock instanceof FileLockImpl)) 120 throw new IOException (); 121 122 FileLockImpl fLockImpl = (FileLockImpl) testedLock; 123 Delegate del = fLockImpl.getDelegate(); 124 125 if (del.getFileLockImpl() != fLockImpl) { 126 throw new IOException (); 127 } 128 129 FileLock retVal = fLockImpl.get(delegate); 130 if (retVal == null) 131 throw new IOException (); 132 133 return retVal; 134 } 135 136 FileObject getPrefered() { 137 final FileObject retVal = get(); 138 FileObject secRetVal = null; 139 if (retVal != null) { 140 if (retVal.isRoot()) { 141 secRetVal = getSecond(); 142 } 143 } 144 return (secRetVal != null) ? secRetVal : retVal; 145 } 146 147 void reset(final ResourcePath resPath) { 148 FileObject lastDelegate = delegate; 149 set(null); 150 setSecond(null); 151 if (get() == null) { 152 boolean folder = (lastDelegate != null) ? lastDelegate.isFolder() : false; 153 delegate = new InvalidDelegate(resPath, folder); 154 } else { 155 getSecond(); 156 attribs = 0; 157 try { 158 reLock(); 159 } catch (IOException e) { 160 Exceptions.printStackTrace(e); 161 } 162 } 163 } 164 165 boolean isValid() { 166 return (delegate != null) && (delegate.isValid()); 167 } 168 169 FileLock lock() throws IOException { 170 FileLockImpl lck; 171 String path = mfo.getPath (); 172 173 synchronized (Delegate.class) { 174 lck = getFileLockImpl(); 175 if (lck != null) throw new FileAlreadyLockedException(path); 176 lock = new WeakReference (lck = new FileLockImpl()); 177 } 178 179 lck.initLock(mfo.getResource().getFile(), get(), getPrefered()); 180 return lck; 181 } 182 183 boolean hasMountAbleFlag() { 184 199 200 return false; 201 } 202 203 void set(final FileObject fo) { 204 synchronized (this) { 205 FileChangeListener oldListener = weakListener; 206 FileObject oldDelegate = delegate; 207 if (oldDelegate == fo) return; 208 209 if (oldListener != null && oldDelegate != null) 210 oldDelegate.removeFileChangeListener(oldListener); 211 212 delegate = fo; 213 if (fo != null) { 214 Class realClass; 219 try { 220 realClass = Class.forName("org.openide.filesystems.FileObject$PriorityFileChangeListener"); 221 } catch (ClassNotFoundException ex) { 222 throw (IllegalStateException )new IllegalStateException (ex.getMessage()).initCause(ex); 223 } 224 weakListener = (FileChangeListener)WeakListeners.create(realClass, FileChangeListener.class, fListener, fo); 225 fo.addFileChangeListener(weakListener); 226 } 227 } 228 } 229 230 private void reLock() throws IOException { 231 final FileLockImpl lck = getFileLockImpl(); 232 if (lck != null) { 233 lck.lock(delegate); 234 lck.lock(secondDelegate); 235 } 236 } 237 238 private FileLockImpl getFileLockImpl() { 239 FileLockImpl lck; 240 synchronized (Delegate.class) { 241 lck = (FileLockImpl) ((lock == null) ? null : lock.get()); 242 } 243 return lck; 244 } 245 246 private void setSecond(final FileObject fo) { 247 synchronized (this) { 248 secondDelegate = fo; 249 } 250 } 251 252 private FileObject getSecond() { 253 ResourcePath resPath = mfo.getResource(); 254 FileObject retVal = secondDelegate; 255 if (retVal == null) { 256 retVal = resolve(resPath, false); 257 setSecond(retVal); 258 } 259 return retVal; 260 } 261 262 private final class FileLockImpl extends FileLock { 263 private final Map lockList = new WeakHashMap (); 264 268 private FileLock mandatoryLock; 269 270 FileLockImpl() { 271 } 272 273 private void initLock(File file, final FileObject delegate, final FileObject prefered) throws IOException { 274 try { 275 lock(delegate); 276 lock(prefered); 277 if (mandatoryLock == null && file != null) { 278 if ((delegate != null && delegate.isData()) || (prefered != null && prefered.isData())) 279 mandatoryLock = WriteLockFactory.tryLock(file, false); 280 } 281 } catch (IOException e) { 282 releaseLock(); 283 throw e; 284 } 285 } 286 287 public void releaseLock() { 288 if (this.isValid()) { 289 super.releaseLock(); 290 if (mandatoryLock != null) { 291 mandatoryLock.releaseLock(); 292 } 293 final Collection locks = lockList.values(); 294 for (Iterator iterator = locks.iterator(); iterator.hasNext();) { 295 FileLock fLock = (FileLock) iterator.next(); 296 fLock.releaseLock(); 297 } 298 299 if (getCurrentLock () == this) { 300 synchronized (Delegate.class) { 301 lock = null; 302 } 303 } 304 } 305 } 306 307 private FileLock getCurrentLock () { 308 return (lock != null) ? (FileLock)lock.get() : null; 309 } 310 311 private void lock(final FileObject delegate) throws IOException { 312 if (delegate != null && this.get(delegate) == null) { 313 FileLock fLock = delegate.lock(); 314 if (mandatoryLock == null && fLock instanceof WriteLock) { 315 mandatoryLock = fLock; 316 } 317 lockList.put(delegate, fLock); 318 } 319 } 320 321 private FileLock get(final FileObject delegate) { 322 return (FileLock) lockList.get(delegate); 323 } 324 325 private Delegate getDelegate() { 326 return Delegate.this; 327 } 328 } 329 private static class TestLockException extends IOException { 330 Map m = new HashMap (); 331 332 void put (FileLockImpl impl, String msg) { 333 m.put(impl, new Exception (msg)); 334 } 335 336 public void printStackTrace(FileLockImpl tested, FileLockImpl current) { 337 Exception exc = (Exception )m.get(tested); 338 if (exc != null) { 339 System.err.println("-------- "+exc.getLocalizedMessage() + " ----------"); 340 exc.printStackTrace(); 341 } 342 Exception exc2 = (Exception )m.get(current); 343 if (exc2 != null) { 344 System.err.println("-------- "+exc2.getLocalizedMessage() + " ----------"); 345 exc2.printStackTrace(); 346 } 347 348 } 349 } 350 351 private static class InvalidDelegate extends InvalidDummy { 352 private final boolean isFolder; 353 354 protected InvalidDelegate(ResourcePath resourcePath, boolean isFolder) { 355 super(resourcePath); 356 this.isFolder = isFolder; 357 } 358 359 public boolean isData() { 360 return !isFolder; 361 } 362 363 public boolean isFolder() { 364 return isFolder; 365 } 366 } 367 } 368 | Popular Tags |