KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > masterfs > filebasedfs > fileobjects > WriteLock


1 /*
2  * The contents of this file are subject to the terms of the Common Development
3  * and Distribution License (the License). You may not use this file except in
4  * compliance with the License.
5  *
6  * You can obtain a copy of the License at http://www.netbeans.org/cddl.html
7  * or http://www.netbeans.org/cddl.txt.
8  *
9  * When distributing Covered Code, include this CDDL Header Notice in each file
10  * and include the License file at http://www.netbeans.org/cddl.txt.
11  * If applicable, add the following below the CDDL Header, with the fields
12  * enclosed by brackets [] replaced by your own identifying information:
13  * "Portions Copyrighted [year] [name of copyright owner]"
14  *
15  * The Original Software is NetBeans. The Initial Developer of the Original
16  * Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
17  * Microsystems, Inc. All Rights Reserved.
18  */

19
20 package org.netbeans.modules.masterfs.filebasedfs.fileobjects;
21
22 import java.io.FileNotFoundException JavaDoc;
23 import java.lang.ref.WeakReference JavaDoc;
24 import java.util.Collections JavaDoc;
25 import java.util.Iterator JavaDoc;
26 import org.netbeans.modules.masterfs.filebasedfs.utils.FSException;
27 import org.openide.filesystems.FileLock;
28
29 import java.io.File JavaDoc;
30 import java.io.IOException JavaDoc;
31 import java.io.RandomAccessFile JavaDoc;
32 import java.lang.ref.Reference JavaDoc;
33 import java.nio.channels.FileChannel JavaDoc;
34 import java.util.ArrayList JavaDoc;
35 import java.util.List JavaDoc;
36 import java.util.Map JavaDoc;
37 import java.util.Set JavaDoc;
38 import java.util.Stack JavaDoc;
39 import java.util.WeakHashMap JavaDoc;
40 import org.openide.filesystems.FileAlreadyLockedException;
41 import org.openide.util.Exceptions;
42 import org.openide.util.NbBundle;
43
44
45 /**
46  * This implementation doesn' allow to get two or more FileLocks for
47  * one identical file. This means that in editor there is possible to open two
48  * editor tabs but there isn't possible to modify them at the same time.
49  *
50  * This implemenation creates new special locking file. This file exists on disk as long
51  * as the FileLock isValid. This locking files are
52  * hidden by FileBasedFileSystem. Moreover this file naming
53  * convention corresponds with defaul regular expression for hiding this files by VisibilityQuery
54  * (just in case that these files wont be hidden FileBasedFileSystem).<P>
55  * <p/>
56  * There might happen that these locking files won't be deleted because of
57  * crash of JVM, not released lock and so one. But these corrupted locks must
58  * be recognized and can't prevent from providing next locks.<P>
59  * <p/>
60  * This implementation isn't responsible:
61  * - for preventing from opening two or more tabs in editor for one file on disk.
62  * - for silent refusing of editing already locked file<P>
63  *
64  * @author Radek Matous
65  */

66
67
68 public class WriteLock extends FileLock {
69     static final Map JavaDoc allLocks = Collections.synchronizedMap(new WeakHashMap JavaDoc());
70     private File JavaDoc lockFile;
71     
72     static {
73         Runtime.getRuntime().addShutdownHook(new Thread JavaDoc() {
74             public void run() {
75                 Set JavaDoc s = allLocks.keySet();
76                 synchronized(allLocks) {
77                     for (Iterator JavaDoc it = s.iterator(); it.hasNext();) {
78                         File JavaDoc f = (File JavaDoc) 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 JavaDoc file) throws IOException JavaDoc {
89         return WriteLock.getInstance(file, false);
90     }
91     
92     static WriteLock tryNioLock(final File JavaDoc file) throws IOException JavaDoc {
93         return WriteLock.getInstance(file, true);
94     }
95
96     static WriteLock tryLightWeightLock(final File JavaDoc file) throws IOException JavaDoc {
97         return WriteLock.getLightWeightInstance(file);
98     }
99
100     public static void relock(final File JavaDoc theOld, File JavaDoc theNew) {
101         List JavaDoc l = new ArrayList JavaDoc();
102         Set JavaDoc s = allLocks.keySet();
103         synchronized(allLocks) {
104             for (Iterator JavaDoc it = s.iterator(); it.hasNext();) {
105                 File JavaDoc f = (File JavaDoc) it.next();
106                 File JavaDoc nLockFile = null;
107                 String JavaDoc relPath = getRelativePath(theOld, f);
108                 if (relPath != null) {
109                     nLockFile = new File JavaDoc(theNew, relPath);
110                 } else if (f.equals(WriteLockUtils.getAssociatedLockFile(theOld))) {
111                     nLockFile = WriteLockUtils.getAssociatedLockFile(theNew);
112                 }
113                 
114                 if (nLockFile != null) {
115                     Reference JavaDoc r = (Reference JavaDoc)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 JavaDoc it2 = l.iterator(); it2.hasNext();) {
127             WriteLock wl = (WriteLock) it2.next();
128             allLocks.put(wl.lockFile, new WeakReference JavaDoc(wl));
129         }
130     }
131     
132     private static String JavaDoc getRelativePath(final File JavaDoc dir, final File JavaDoc file) {
133         Stack JavaDoc stack = new Stack JavaDoc ();
134         File JavaDoc 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 JavaDoc retval = new StringBuilder JavaDoc();
141         while (!stack.isEmpty()) {
142             retval.append((String JavaDoc)stack.pop());
143             if (!stack.isEmpty()) {
144                 retval.append("/");//NOI18N
145
}
146         }
147         return retval.toString();
148     }
149     
150     
151     private static WriteLock getLightWeightInstance(final File JavaDoc file) throws IOException JavaDoc {
152         File JavaDoc 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 JavaDoc file, boolean nioLock) throws IOException JavaDoc {
163         boolean isCreated = false;
164         IOException JavaDoc toFire = null;
165         
166         File JavaDoc lckFile = WriteLockUtils.getAssociatedLockFile(file);
167         if (!lckFile.exists()) {
168             isCreated = true;
169         }
170         RandomAccessFile JavaDoc raf = getAccessToFile(lckFile);//NOI18N
171
assert lckFile.exists();
172         
173         FileChannel JavaDoc channel = raf.getChannel();
174         
175         
176         if (channel != null && channel.isOpen()) {
177             try {
178                 String JavaDoc 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 JavaDoc(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 JavaDoc 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 JavaDoc getAccessToFile(final File JavaDoc f) throws FileNotFoundException JavaDoc {
218         RandomAccessFile JavaDoc raf = null;
219         try {
220             raf = new RandomAccessFile JavaDoc(f, "rwd");//NOI18N
221
} catch (FileNotFoundException JavaDoc e) {
222             FileNotFoundException JavaDoc fex = e;
223             if (!f.exists()) {
224                 fex = (FileNotFoundException JavaDoc)new FileNotFoundException JavaDoc(e.getLocalizedMessage()).initCause(e);
225             } else if (!f.canRead()) {
226                 fex = (FileNotFoundException JavaDoc)new FileNotFoundException JavaDoc(e.getLocalizedMessage()).initCause(e);
227             } else if (!f.canWrite()) {
228                 fex = (FileNotFoundException JavaDoc)new FileNotFoundException JavaDoc(e.getLocalizedMessage()).initCause(e);
229             } else if (f.getParentFile() == null) {
230                 fex = (FileNotFoundException JavaDoc)new FileNotFoundException JavaDoc(e.getLocalizedMessage()).initCause(e);
231             } else if (!f.getParentFile().exists()) {
232                 fex = (FileNotFoundException JavaDoc)new FileNotFoundException JavaDoc(e.getLocalizedMessage()).initCause(e);
233             }
234             throw fex;
235         }
236         return raf;
237     }
238     
239     
240     private WriteLock(File JavaDoc lockFile) {
241         this.lockFile = lockFile;
242         register();
243     }
244     
245     public boolean isValid(final File JavaDoc f) {
246         boolean retVal = isValid();
247         
248         if (retVal) {
249             final File JavaDoc 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                     //assert isDeleted : getLockFile().getAbsolutePath();
264
}
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 JavaDoc(this));
275     }
276     
277     final File JavaDoc getLockFile() {
278         return lockFile;
279     }
280     
281     public final String JavaDoc toString() {
282         final String JavaDoc name = getLockFile().getName();
283         final String JavaDoc newName = name.substring(WriteLockUtils.PREFIX.length(), (name.length() - WriteLockUtils.SUFFIX.length()));
284         return new File JavaDoc(getLockFile().getParentFile(), newName).getAbsolutePath();
285     }
286     
287     private static class NioLock extends WriteLock {
288         private FileChannel JavaDoc channel;
289         private java.nio.channels.FileLock JavaDoc nioLock;
290         
291         NioLock(File JavaDoc lockFile, FileChannel JavaDoc channel, java.nio.channels.FileLock JavaDoc 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 JavaDoc e) {
313                     Exceptions.printStackTrace(e);
314                 }
315                 
316                 super.releaseLock();
317             }
318         }
319     }
320 }
321
Popular Tags