KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > netbeans > modules > masterfs > MasterFileObject


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
21 package org.netbeans.modules.masterfs;
22
23 import java.io.File JavaDoc;
24 import org.netbeans.modules.masterfs.filebasedfs.FileBasedFileSystem;
25 import org.netbeans.modules.masterfs.filebasedfs.fileobjects.BaseFileObj;
26 import org.openide.filesystems.*;
27 import org.openide.util.Utilities;
28 import org.netbeans.modules.masterfs.filebasedfs.fileobjects.ReplaceForSerialization;
29 import javax.swing.event.EventListenerList JavaDoc;
30 import java.io.IOException JavaDoc;
31 import java.io.InputStream JavaDoc;
32 import java.io.OutputStream JavaDoc;
33 import java.util.*;
34 import java.util.logging.Level JavaDoc;
35 import java.util.logging.Logger JavaDoc;
36 import org.netbeans.modules.masterfs.filebasedfs.fileobjects.FileObj;
37 import org.netbeans.modules.masterfs.filebasedfs.fileobjects.FolderObj;
38 import org.netbeans.modules.masterfs.filebasedfs.utils.FileInfo;
39 import org.netbeans.modules.masterfs.providers.ProvidedExtensions;
40 import org.openide.util.Exceptions;
41
42 /**
43  * Implements FileObject, hosts delegate and mostly uses it whenever possible.
44  *
45  * @author Radek Matous
46  */

47 final class MasterFileObject extends BasedOnResourcePath {
48     /** generated Serialized Version UID */
49     static final long serialVersionUID = -1244651324997356809L;
50     transient private final Delegate delegate;
51     /** listeners - registered to listen on this FileObject*/
52     transient private EventListenerList JavaDoc listeners;
53
54     private static final FileSystem.AtomicAction referenceAction = new MasterFileObject.AtomicAction (null);
55     transient private boolean isFolder;
56     
57
58     /** Don`t call this constructor directly, use rather getOrCreate*/
59     MasterFileObject(ResourcePath resourceName, FileObject deleg) {
60         super(resourceName);
61         if (deleg != null) {
62             isFolder = deleg.isFolder();
63         } else {
64             File JavaDoc f = resourceName.getFile();
65             if (f != null) {
66                 isFolder = f.isDirectory();
67             } else {
68                 isFolder = true;
69             }
70         }
71         delegate = new Delegate(deleg, new FileChangeListenerImpl(), this);
72         delegate.set(deleg);
73     }
74
75     /**
76      * Implements abstract FileObject.lastModified()
77      */

78     public java.util.Date JavaDoc lastModified() {
79         FileObject deleg = getValidOrInvalid(getDelegate().getPrefered());
80         return deleg.lastModified();
81     }
82
83     /**
84      * Implements abstract FileObject.isValid()
85      */

86     public boolean isValid() {
87         FileObject deleg = getValidOrInvalid(getDelegate().getPrefered());
88         File JavaDoc f = (deleg.isVirtual()) ? null: getResource().getFile();
89         return (f != null) ? (deleg.isValid() && (f.exists())) : deleg.isValid();
90     }
91
92     /**
93      * Implements abstract FileObject.getAttribute(String attrName)
94      */

95     public Object JavaDoc getAttribute(String JavaDoc attrName) {
96         if (attrName.equals("FileSystem.rootPath")) {
97             return "";//NOI18N
98
}
99         
100         if (attrName.equals("java.io.File")) {
101             File JavaDoc file = getResource().getFile();
102             if (file != null && file.exists()) {
103                 return file;
104             }
105         }
106         
107         
108         FileObject deleg = getValidOrInvalid(getDelegate().getPrefered());
109         Object JavaDoc attribute = deleg.getAttribute(attrName);
110         if (attribute == null) {
111             FileObject secDeleg = getDelegate().get();
112             if (secDeleg != null && secDeleg.isValid() && secDeleg.isRoot()) {
113                 attribute = secDeleg.getAttribute(attrName);
114             }
115         }
116         return attribute;
117     }
118
119     /**
120      * Implements abstract FileObject.setAttribute(String attrName, Object value)
121      */

122     public void setAttribute(final String JavaDoc attrName, final Object JavaDoc value) throws IOException JavaDoc {
123         FileObject deleg = getValidOrInvalid(getDelegate().getPrefered());
124         deleg.setAttribute(attrName, value);
125     }
126
127     /**
128      * Implements abstract FileObject.getAttributes()
129      */

130     public Enumeration getAttributes() {
131         FileObject deleg = getValidOrInvalid(getDelegate().getPrefered());
132         return deleg.getAttributes();
133     }
134
135     /**
136      * Implements abstract FileObject.getSize()
137      */

138     public long getSize() {
139         FileObject deleg = getValidOrInvalid(getDelegate().getPrefered());
140         return deleg.getSize();
141     }
142
143     /**
144      * Implements abstract FileObject.getInputStream()
145      */

146     public InputStream JavaDoc getInputStream() throws java.io.FileNotFoundException JavaDoc {
147         FileObject deleg = getValidOrInvalid(getDelegate().getPrefered());
148         return deleg.getInputStream();
149     }
150
151     /**
152      * Implements abstract FileObject.getOutputStream(FileLock lock)
153      */

154     public OutputStream JavaDoc getOutputStream(FileLock lock) throws java.io.IOException JavaDoc {
155         FileObject deleg = getValidOrInvalid(getDelegate().getPrefered());
156         FileLock lck = (deleg.isValid()) ? Delegate.getLockForDelegate(lock, deleg) : null;
157
158         return (deleg instanceof FileObj)? ((FileObj)deleg).getOutputStream(lck, getExtensions(), this)
159                 : deleg.getOutputStream(lck);
160     }
161
162     /**
163      * Implements abstract FileObject.lock()
164      */

165     public FileLock lock() throws IOException JavaDoc {
166         return getDelegate().lock();
167     }
168
169     /**
170      * Implements abstract FileObject.setImportant(boolean b)
171      */

172     public void setImportant(final boolean b) {
173         FileObject deleg = getValidOrInvalid(getDelegate().get());
174         deleg.setImportant(b);
175     }
176
177
178     /**
179      * Implements abstract FileObject.isReadOnly()
180      */

181     public boolean isReadOnly() {
182         FileObject deleg = getValidOrInvalid(getDelegate().getPrefered());
183         return deleg.isReadOnly();
184     }
185
186     /**
187      * Implements FileObject.getMIMEType()
188      */

189     public String JavaDoc getMIMEType() {
190         FileObject deleg = getValidOrInvalid(getDelegate().get());
191         return deleg.getMIMEType();
192     }
193
194     /**
195      * Implements FileObject.existsExt(String extI)
196      */

197     public boolean existsExt(String JavaDoc ext) {
198         FileObject deleg = getValidOrInvalid(getDelegate().getPrefered());
199         return deleg.existsExt(ext);
200     }
201
202     /**
203      * Implements abstract FileObject.isData()
204      */

205     public boolean isData() {
206         return (!isFolder());
207     }
208
209     /**
210      * Implements abstract FileObject.isFolder()
211      */

212     public boolean isFolder() {
213 /*
214         if (getDelegate().hasMountAbleFlag()) return true;
215
216         FileObject deleg = getValidOrInvalid(getDelegate().get(true));
217         return deleg.isFolder();
218 */

219         return isFolder;
220     }
221
222     /**
223      * Implements FileObject.isVirtual()
224      */

225     public boolean isVirtual() {
226         FileObject deleg = getValidOrInvalid(getDelegate().get());
227         return deleg.isVirtual();
228     }
229
230     /**
231      * Implements abstract FileObject.addFileChangeListener(FileChangeListener fcl)
232      */

233     public void addFileChangeListener(final FileChangeListener fcl) {
234         synchronized (this) {
235             if (listeners == null) {
236                 listeners = new EventListenerList JavaDoc();
237             }
238             listeners.add(FileChangeListener.class, fcl);
239         }
240     }
241
242     /**
243      * Implements abstract FileObject.removeFileChangeListener(FileChangeListener fcl)
244      */

245     public void removeFileChangeListener(FileChangeListener fcl) {
246         synchronized (this) {
247             if (listeners != null) {
248                 listeners.remove(FileChangeListener.class, fcl);
249             }
250         }
251     }
252
253     /**
254      * Implements abstract FileObject.transformChildren()
255      */

256     public FileObject[] getChildren() {
257         //TODO: tryAutoMount() causes #42772: Deadlock in masterfs
258
//tryAutoMount();
259
enterCriticalSection();
260         try {
261             FileObject deleg = getValidOrInvalid(getDelegate().get());
262             return transformChildren(deleg.getChildren());
263         } finally {
264             finishCriticalSection();
265         }
266     }
267
268     /**
269      * Implements abstract FileObject.getFileObject(String nameI, String extI)
270      */

271     public FileObject getFileObject(String JavaDoc name, String JavaDoc ext) {
272         //TODO: tryAutoMount() causes #42772: Deadlock in masterfs
273
//tryAutoMount();
274
ResourcePath parentResource = getResource();
275         ResourcePath childResourcePath = parentResource.getChild(name, ext);
276         FileObject retVal = null;
277             /*since rev. 1.31 added following condition cause
278             #47885: MasterFS impl of FileObject.getFileObject() should be tighten up
279              */

280         if (childResourcePath != null && parentResource.equals(childResourcePath.getParent())) {
281             FileObject deleg = getValidOrInvalid(getDelegate().get());
282             if (!(deleg instanceof SpecialDelegates.WinRootVirtual)) {//#54856
283
FileObject child = deleg.getFileObject(name, ext);
284                 retVal = (child != null) ? transformChild(child) : null;
285             } else {
286                 retVal = getCache().getOrCreate(childResourcePath);
287             }
288             
289             
290             if (retVal == null) {
291                 File JavaDoc f = childResourcePath.getFile();
292                 boolean canRefresh = true;
293                 if ((Utilities.isWindows() || (Utilities.getOperatingSystem() == Utilities.OS_OS2)) && childResourcePath.getParent().isRoot()) {
294                     canRefresh = (SpecialDelegates.checkValidWindowsDrive(f) != null);
295                 }
296                 if (canRefresh) {
297                     if (f != null && f.exists()) {
298                         this.refresh();
299                         if (!(deleg instanceof SpecialDelegates.WinRootVirtual)) {//#54856
300
FileObject child = deleg.getFileObject(name, ext);
301                             retVal = (child != null) ? transformChild(child) : null;
302                         } else {
303                             retVal = getCache().getOrCreate(childResourcePath);
304                         }
305                         
306                     }
307                 }
308             }
309         }
310         return retVal;
311     }
312     /**
313      * Implements FileObject.transformChildren(boolean rec)
314      */

315     public Enumeration getChildren(boolean rec) {
316         Enumeration my = org.openide.util.Enumerations.array (this.getChildren());
317         
318         if (rec == false)
319             return my;
320
321         return org.openide.util.Enumerations.queue (
322             my, getChildsEnum ()
323         );
324     }
325
326     /**
327      * Implements FileObject.getFolders(boolean rec)
328      */

329     public Enumeration getFolders(boolean rec) {
330         return org.openide.util.Enumerations.filter (
331             getChildren (rec), new AcceptFolders (true)
332         );
333     }
334
335     /**
336      * Implements FileObject.getData(boolean rec)
337      */

338     public Enumeration getData(boolean rec) {
339         return org.openide.util.Enumerations.filter (
340             getChildren (rec), new AcceptFolders (false)
341         );
342     }
343
344     /** Selector from folders and data files.
345      */

346     private final class AcceptFolders implements org.openide.util.Enumerations.Processor {
347         private boolean folders;
348         
349         public AcceptFolders (boolean folders) {
350             this.folders = folders;
351         }
352         
353         public Object JavaDoc process (Object JavaDoc o, Collection nothing) {
354             final FileObject fo = (FileObject) o;
355             if (folders) {
356                 return fo.isFolder() ? fo : null;
357             } else {
358                 return fo.isData() ? fo : null;
359             }
360         }
361     } // end of AcceptFolders
362

363     /**
364      * Implements abstract FileObject.getFileSystem()
365      */

366
367     public FileSystem getFileSystem() throws FileStateInvalidException {
368         return MasterFileSystem.getDefault();
369     }
370
371     /**
372      * Implements abstract FileObject.createFolder(String nameI)
373      */

374     public FileObject createFolder(final String JavaDoc name) throws IOException JavaDoc {
375         if (name.indexOf('\\') != -1 || name.indexOf('/') != -1) {//NOI18N
376
throw new IllegalArgumentException JavaDoc(name);
377         }
378         
379         MasterFileSystem.StatusImpl status = (MasterFileSystem.StatusImpl)MasterFileSystem.getDefault().getStatus();
380         ProvidedExtensions extensions = status.getExtensions();
381         extensions.beforeCreate(this, name, true);
382         IOException JavaDoc toThrow = null;
383         FileObject newFolder = null;
384         try {
385             newFolder = new AtomicAction(this).createFolder(name);
386             extensions.createSuccess(newFolder);
387             return newFolder;
388         } catch(IOException JavaDoc iex) {
389             extensions.createFailure(this, name, true);
390             throw iex;
391         }
392     }
393
394     /**
395      * Implements FileObject.createData(String nameI)
396      */

397     public FileObject createData(final String JavaDoc name) throws IOException JavaDoc {
398         if (name.indexOf('\\') != -1 || name.indexOf('/') != -1) {//NOI18N
399
throw new IllegalArgumentException JavaDoc(name);
400         }
401         
402         MasterFileSystem.StatusImpl status = (MasterFileSystem.StatusImpl)MasterFileSystem.getDefault().getStatus();
403         ProvidedExtensions extensions = status.getExtensions();
404         extensions.beforeCreate(this, name, false);
405         IOException JavaDoc toThrow = null;
406         FileObject newFile = null;
407         try {
408             newFile = new AtomicAction(this).createData(name);
409             extensions.createSuccess(newFile);
410             return newFile;
411         } catch(IOException JavaDoc iex) {
412             extensions.createFailure(this, name, false);
413             throw iex;
414         }
415     }
416
417     /**
418      * Implements abstract FileObject.createData(String nameI, String extI)
419      */

420     public FileObject createData(final String JavaDoc name, final String JavaDoc ext) throws IOException JavaDoc {
421         if (name.indexOf('\\') != -1 || name.indexOf('/') != -1) {//NOI18N
422
throw new IllegalArgumentException JavaDoc(name);
423         }
424         
425         MasterFileSystem.StatusImpl status = (MasterFileSystem.StatusImpl)MasterFileSystem.getDefault().getStatus();
426         ProvidedExtensions extensions = status.getExtensions();
427         extensions.beforeCreate(this, FileInfo.composeName(name, ext), false);
428         IOException JavaDoc toThrow = null;
429         FileObject newFile = null;
430         try {
431             newFile = new AtomicAction(this).createData(name, ext);
432             extensions.createSuccess(newFile);
433             return newFile;
434         } catch(IOException JavaDoc iex) {
435             extensions.createFailure(this, FileInfo.composeName(name, ext), false);
436             throw iex;
437         }
438     }
439
440     /**
441      * Implements abstract FileObject.copy (FileObject target, String nameI, String extI)
442      */

443     public FileObject copy(FileObject target, String JavaDoc name, String JavaDoc ext) throws IOException JavaDoc {
444         // overwritten only because of included in sync. section
445
return new AtomicAction(this).copy(target, name, ext);
446     }
447
448     /**
449      * Implements abstract FileObject.delete(FileLock lock)
450      */

451     public void delete(FileLock lock) throws IOException JavaDoc {
452         if (getDelegate().hasMountAbleFlag() ||
453                 MountTable.getDefault().getMountedFileSystem(this.getResource().getNormalizedPath()) != null) {
454             FileObject deleg = getDelegate().get();
455             if (deleg != null && deleg.isRoot())
456                 MountTable.getDefault().unmount(getDelegateFileSystem());
457         }
458         MasterFileSystem.StatusImpl status = (MasterFileSystem.StatusImpl)MasterFileSystem.getDefault().getStatus();
459         ProvidedExtensions extensions = status.getExtensions();
460         extensions.beforeDelete(this);
461         IOException JavaDoc toThrow = null;
462         try {
463             new AtomicAction(this).delete(lock);
464         } catch(IOException JavaDoc iex) {
465             toThrow = iex;
466             throw iex;
467         } finally {
468             if (toThrow == null) {
469                 extensions.deleteSuccess(this);
470             } else {
471                 extensions.deleteFailure(this);
472             }
473         }
474     }
475
476     /**
477      * Implements abstract FileObject.move (FileLock lock, FileObject target, String nameI, String extI)
478      */

479     public FileObject move(FileLock lock, FileObject target, String JavaDoc name, String JavaDoc ext) throws IOException JavaDoc {
480         // overwritten only because of included in sync. section
481
enterExclusiveCriticalSection();
482         try {
483             if (getParent().equals(target)) {
484                 rename(lock,name, ext);
485                 return this;
486             }
487             return new AtomicAction(this).move(lock, target, name, ext);
488         } finally {
489             finishExclusiveCriticalSection();
490         }
491     }
492
493     private FileObject superMove(FileLock lock, FileObject target, String JavaDoc name, String JavaDoc ext) throws IOException JavaDoc {
494         return super.move(lock, target, name, ext);
495     }
496
497     /**
498      * Implements FileObject.refresh(boolean expected)
499      */

500     public void refresh(final boolean expected) {
501         try {
502             if (expected)
503                 new AtomicAction(this).refreshExpected();
504             else
505                 new AtomicAction(this).refresh();
506         } catch (IOException JavaDoc e) {
507             // shouldn't occure
508
Exceptions.printStackTrace(e);
509         }
510     }
511
512     /**
513      * Implements abstract FileObject.getParent()
514      */

515     public FileObject getParent() {
516         FileObject retVal = null;
517         ResourcePath parentRes = getResource().getParent();
518         if (parentRes != null) {
519             parentRes = (parentRes.getParent() == null) ? ResourcePath.getRoot() : parentRes;
520             retVal = Cache.getDefault().getOrCreate(parentRes);
521             if (retVal == null) {
522                 retVal = Cache.getDefault().getValidOrInvalid(parentRes);
523             }
524         }
525         return retVal;
526     }
527
528     /**
529      * Implements abstract FileObject.rename()
530      *
531      * Note: uses fs.unmount uses exclusiveSection, then this method rename should not
532      * be called from synchronized section inside MasterFileObject.
533      */

534     public void rename(FileLock lock, String JavaDoc name, String JavaDoc ext) throws IOException JavaDoc {
535         //TODO: rename is wrong implemeted
536
FileObject deleg = null;
537         ProvidedExtensions.IOHandler renameHandler = getRenameHandler(name, ext);
538         enterCriticalSection();
539         try {
540             deleg = getValidOrInvalid(getDelegate().get());
541             if (isReadOnly()) {
542                 Utils.throwIOException("EXC_CannotRename",
543                         new Object JavaDoc[]{getPath(), getHFs().getDisplayName()});
544             }
545
546             ResourcePath oldResName = getResource();
547             //TODO: should'nt be renamed before deleg.rename, which can fail
548
//TODO: write new test, if also children were renamed
549
setResource(oldResName.getParent().getChild(name, ext));
550             Cache.getDefault().replace(oldResName.getNormalizedPath(), this);
551             if (isRoot() || !deleg.isRoot()) {
552                 try {
553                     //TODO: here is fired exception sometimes
554
FileLock lck = Delegate.getLockForDelegate(lock, deleg);
555                     if (renameHandler == null) {
556                         deleg.rename(lck, name, ext);
557                     } else {
558                         ((BaseFileObj)deleg).rename(lck, name, ext, renameHandler);
559                     }
560                     MountTable.getDefault().renameCachedFileObjects(oldResName.getNormalizedPath(), getResource().getNormalizedPath());
561                     return;
562                 } catch (IOException JavaDoc iex) {
563                     setResource(oldResName);
564                     throw iex;
565                 }
566             }
567             // ugly, time consuming piece of code:
568
// fs must be unmounted, renamed and mounted again
569
// Can`t be implemented before SPI will be introduced
570
// because there is no uniform manner how to create filesystems:
571
// something like createFileSystem (java.io.File)
572
//deleg = Delegate.getPrefered(this);
573
throw new IOException JavaDoc("Not implemented yet");
574         } finally {
575             finishCriticalSection();
576         }
577     }
578     
579     private ProvidedExtensions.IOHandler getRenameHandler(final String JavaDoc name, final String JavaDoc ext) {
580         ProvidedExtensions pe;
581         pe = ((MasterFileSystem.StatusImpl)MasterFileSystem.getDefault().getStatus()).getExtensions();
582
583         File JavaDoc fileToRename = getResource().getFile();
584         return pe.getRenameHandler(fileToRename, FileInfo.composeName(name, ext));
585     }
586
587     public final Object JavaDoc writeReplace() {
588         return new Replace(getPath());
589     }
590
591     Delegate getDelegate() {
592         return delegate;
593     }
594
595     private static MasterFileSystem getHFs() {
596         return MasterFileSystem.getDefault();
597     }
598
599     private static Cache getCache() {
600         return Cache.getDefault();
601     }
602
603     private MasterFileObject[] transformChildren(FileObject[] delegs) {
604         final ArrayList aList = new ArrayList(delegs.length);
605         for (int i = 0; i < delegs.length; i++) {
606             FileObject hfo = transformChild(delegs[i]);
607             if (hfo != null)
608                 aList.add(hfo);
609         }
610         MasterFileObject[] retVal = new MasterFileObject[aList.size()];
611         aList.toArray(retVal);
612         return retVal;
613     }
614
615     private FileObject transformChild(final FileObject deleg) {
616         FileObject hfo;
617         if (deleg instanceof InvalidDummy) {
618             InvalidDummy res = (InvalidDummy) deleg;
619             hfo = getCache().getOrCreate(res.getResource());
620         } else {
621             ResourcePath res = getResource().getChild(deleg.getNameExt());
622             if (MountTable.getDefault().getMountedFileSystem(res.getNormalizedPath()) != null)
623                 hfo = getCache().getOrCreate(res, null);
624             else
625                 hfo = getCache().getOrCreate(res, deleg);
626         }
627         return hfo;
628     }
629
630     private void tryAutoMount() {
631         SyncSection.getDefault().enterExclusiveSection();
632         try {
633             FileObject deleg = getDelegate().get();
634             if (getDelegate().hasMountAbleFlag() && deleg != null && !deleg.isRoot()) {
635                 FileSystem fs = ProviderCall.createFileSystem(getPath());
636                 if (fs != null) {
637                     try {
638                         MountTable.getDefault().mount(getPath(), fs);
639                     } catch (IOException JavaDoc iex) {
640                         Exceptions.printStackTrace(iex);
641                     }
642                 }
643             }
644         } finally {
645             SyncSection.getDefault().finishExclusiveSection();
646         }
647
648     }
649
650     /** Transforms fe.getFile to it`s wraper*/
651     private MasterFileObject eventFileToMasterFileObject(FileEvent fe) {
652         FileObject file = fe.getFile();
653         if (file != null) {
654             FileObject dFile = null;
655             ResourcePath child = getResource().getChild(file.getNameExt());
656             
657             dFile = getCache().get(child);
658             
659             if (file.isVirtual() && !file.isValid() && dFile == null) {
660                 //hack for #56995
661
FileObject file56995 = getCache().getValidOrInvalid(child);
662                 if (file56995 != null && file56995.isVirtual()) {
663                     dFile = file56995;
664                 }
665             }
666                        
667             dFile = (dFile != null) ? dFile : getCache().getOrCreate(child);
668             dFile = (dFile != null) ? dFile : getCache().getValidOrInvalid(child);
669             dFile = (dFile != null) ? dFile : this;
670             return (MasterFileObject) dFile;
671         }
672         return this;
673     }
674
675
676     private org.openide.util.Enumerations.Processor getChildsEnum() {
677         return new org.openide.util.Enumerations.Processor () {
678             public Object JavaDoc process(final Object JavaDoc o, Collection toAdd) {
679                 final FileObject fo = (FileObject) o;
680                 if (fo != null)
681                     toAdd.addAll (Arrays.asList (fo.getChildren()));
682                 return fo;
683             }
684         };
685     }
686
687
688     private Enumeration getEnumOfListeners() {
689         Object JavaDoc[] fcls;
690         synchronized (this) {
691             if (listeners == null) {
692                 return org.openide.util.Enumerations.empty();
693             }
694             fcls = listeners.getListenerList();
695         }
696
697         if (fcls == null || fcls.length == 0) {
698             return org.openide.util.Enumerations.empty();
699         }
700
701         class OnlyListeners implements org.openide.util.Enumerations.Processor {
702             public Object JavaDoc process(final Object JavaDoc o, Collection toAdd) {
703                 if (o instanceof FileChangeListener) {
704                     return o;
705                 }
706                 return null;
707             }
708         }
709         
710         return org.openide.util.Enumerations.filter (
711             org.openide.util.Enumerations.array (fcls), new OnlyListeners ()
712         );
713     }
714
715     FileSystem getDelegateFileSystem() {
716         FileObject deleg = getDelegate().get();
717         try {
718             return (deleg != null) ? deleg.getFileSystem() : null;
719         } catch (FileStateInvalidException fsx) {
720             Logger.getAnonymousLogger().log(Level.WARNING, null, fsx);
721         }
722         return null;
723     }
724
725     static void refreshAfterMount(FileObject newDelegate, FileObject oldDelegate, MasterFileObject hfo) {
726         ResourcePath parentRes = hfo.getResource().getParent();
727         MasterFileObject parent = (parentRes != null) ? getCache().get(parentRes) : null;
728
729         // basically refresh on file
730
if (newDelegate != null) {
731             // added children
732
boolean isRootFileSystem = false;
733             try {
734                 isRootFileSystem = (newDelegate.getFileSystem() instanceof FileBasedFileSystem);
735             } catch (FileStateInvalidException fsx) {
736                 Logger.getAnonymousLogger().log(Level.WARNING, null, fsx);
737             }
738             
739             if (newDelegate.isFolder() && !isRootFileSystem) {
740                 // compare old children and new children
741
Set oldChildren = new HashSet(Arrays.asList(oldDelegate.getChildren()));
742                 Set newChildren = new HashSet(Arrays.asList(newDelegate.getChildren()));
743                 retainOnlyDifferent(oldChildren, newChildren);
744                 handleCreated(newChildren, hfo);
745             }
746             // changed
747

748 /*
749             if (oldDelegate.isFolder() == newDelegate.isFolder()) {
750                 handleChanged(hfo, parent);
751             }
752 */

753         } else {
754             // deleted
755
handleDeleted(hfo, parent);
756         }
757     }
758
759     private static void handleDeleted(MasterFileObject hfo, MasterFileObject parent) {
760         hfo.fireFileDeletedEvent(hfo.getEnumOfListeners(), new FileEvent(hfo));
761         if (parent != null)
762             parent.fireFileDeletedEvent(parent.getEnumOfListeners(), new FileEvent(parent, hfo));
763     }
764
765     private static void handleChanged(MasterFileObject hfo, MasterFileObject parent) {
766         hfo.fireFileChangedEvent(hfo.getEnumOfListeners(), new FileEvent(hfo));
767         if (parent != null)
768             parent.fireFileChangedEvent(parent.getEnumOfListeners(), new FileEvent(parent, hfo));
769     }
770
771     private static void handleCreated(Set newChildren, MasterFileObject hfo) {
772         Iterator addIt = newChildren.iterator();
773         while (addIt.hasNext()) {
774             FileObject addDeleg = (FileObject) addIt.next();
775             ResourcePath name = hfo.getResource().getChild(addDeleg.getNameExt());
776             MasterFileObject addHfo = getCache().get(name);
777             boolean resetDelg = false;
778             if (addHfo == null) {
779                 addHfo = getCache().getOrCreate(name, addDeleg);
780                 resetDelg = true;
781             }
782             if (addHfo.isFolder())
783                 hfo.fireFileFolderCreatedEvent(hfo.getEnumOfListeners(), new FileEvent(hfo, addHfo));
784             else
785                 hfo.fireFileDataCreatedEvent(hfo.getEnumOfListeners(), new FileEvent(hfo, addHfo));
786
787             if (resetDelg)
788                 addHfo.getDelegate ().reset(addHfo.getResource());
789         }
790     }
791
792     private static void retainOnlyDifferent(Set oldChildren, Set newChildren) {
793         Iterator oldIt = oldChildren.iterator();
794         Iterator newIt = newChildren.iterator();
795         while (oldIt.hasNext()) {
796             if (!newIt.hasNext()) break;
797             FileObject oldFo = (FileObject) oldIt.next();
798             while (newIt.hasNext()) {
799                 FileObject newFo = (FileObject) newIt.next();
800                 if (newFo.getNameExt().equals(oldFo.getNameExt())) {
801                     newIt.remove();
802                     oldIt.remove();
803                     break;
804                 }
805             }
806             newIt = newChildren.iterator();
807         }
808     }
809
810     private FileObject getValidOrInvalid(FileObject deleg) {
811         return getValidOrInvalid(deleg, this);
812     }
813
814     private static FileObject getValidOrInvalid(FileObject deleg, final MasterFileObject hfo) {
815         if (deleg == null) deleg = new InvalidDummy(hfo.getResource());
816         return deleg;
817     }
818
819     private void finishCriticalSection() {
820         SyncSection.getDefault().finishSection();
821     }
822
823     private void enterCriticalSection() {
824         SyncSection.getDefault().enterSection();
825     }
826
827     private void finishExclusiveCriticalSection() {
828         SyncSection.getDefault().finishExclusiveSection();
829     }
830
831     private void enterExclusiveCriticalSection() {
832         SyncSection.getDefault().enterExclusiveSection();
833     }
834
835     public boolean canWrite() {
836         return !isReadOnly();
837     }
838
839     public static final class Replace extends Object JavaDoc implements java.io.Serializable JavaDoc {
840         /** generated Serialized Version UID */
841         static final long serialVersionUID = -8552332135435542113L;
842         private final String JavaDoc path;
843
844         /** Constructor
845          */

846         public Replace(final String JavaDoc path) {
847             this.path = path;
848         }
849
850         /** Finds the right file.
851          */

852         public Object JavaDoc readResolve() {
853             FileSystem fs = MasterFileSystem.getDefault();
854             FileObject retVal = fs == null ? null : fs.findResource(path);
855             if (retVal == null) {
856                 retVal = (FileObject)new ReplaceForSerialization(new File JavaDoc (path)).readResolve();
857             }
858             return retVal;
859         }
860
861     } // end of Replace
862

863     private final class FileChangeListenerImpl implements FileChangeListener {
864         /**
865          * Implements FileChangeListener.fileDataCreated(FileEvent fe)
866          */

867         public void fileDataCreated(FileEvent fe) {
868             MasterFileObject eventFile = eventFileToMasterFileObject(fe);
869             FileEvent fe2Fire = new FileEvent(MasterFileObject.this, eventFile, fe.isExpected());
870             FileObject eventFileDelegate = eventFile.getDelegate().get();
871             FileObject meDelegate = MasterFileObject.this.getDelegate().get();
872             
873             if (eventFileDelegate == fe.getFile() && meDelegate == fe.getSource()) {
874                 fireFileDataCreatedEvent(getEnumOfListeners(), fe2Fire);
875             }
876         }
877
878         /**
879          * Implements FileChangeListener.fileFolderCreated(FileEvent fe)
880          */

881         public void fileFolderCreated(FileEvent fe) {
882             MasterFileObject eventFile = eventFileToMasterFileObject(fe);
883             FileEvent fe2Fire = new FileEvent(MasterFileObject.this, eventFile, fe.isExpected());
884             FileObject eventFileDelegate = eventFile.getDelegate().get();
885             FileObject meDelegate = MasterFileObject.this.getDelegate().get();
886             
887             if (eventFileDelegate == fe.getFile() && meDelegate == fe.getSource()) {
888                 fireFileFolderCreatedEvent(getEnumOfListeners(), fe2Fire);
889             }
890         }
891
892         /**
893          * Implements FileChangeListener.fileDeleted(FileEvent fe)
894          */

895         public void fileDeleted(FileEvent fe) {
896             MasterFileObject eventFile = eventFileToMasterFileObject(fe);
897             FileEvent fe2Fire = new FileEvent(MasterFileObject.this, eventFile, fe.isExpected());
898             FileObject eventFileDelegate = eventFile.getDelegate().get();
899             FileObject meDelegate = MasterFileObject.this.getDelegate().get();
900             if (eventFileDelegate == fe.getFile() && meDelegate == fe.getSource()) {
901                 fireFileDeletedEvent(getEnumOfListeners(), fe2Fire);
902             }
903         }
904
905         /**
906          * Implements FileChangeListener.fileChanged(FileEvent fe)
907          */

908         public void fileChanged(FileEvent fe) {
909             MasterFileObject eventFile = eventFileToMasterFileObject(fe);
910             FileEvent fe2Fire = new FileEvent(MasterFileObject.this, eventFile, fe.isExpected());
911             FileObject eventFileDelegate = eventFile.getDelegate().get();
912             FileObject meDelegate = MasterFileObject.this.getDelegate().get();
913             
914             if (eventFileDelegate == fe.getFile() && meDelegate == fe.getSource()) {
915                 fireFileChangedEvent(getEnumOfListeners(), fe2Fire);
916             }
917         }
918
919         /**
920          * Implements FileChangeListener.fileRenamed(FileRenameEvent fe)
921          */

922         public void fileRenamed(FileRenameEvent fe) {
923             String JavaDoc name = fe.getName();
924             String JavaDoc ext = fe.getExt();
925
926             MasterFileObject eventFile = eventFileToMasterFileObject(fe);
927             FileRenameEvent fe2Fire = new FileRenameEvent(MasterFileObject.this, eventFile, name, ext);
928             FileObject eventFileDelegate = eventFile.getDelegate().get();
929             FileObject meDelegate = MasterFileObject.this.getDelegate().get();
930             
931             if (eventFileDelegate == fe.getFile() && meDelegate == fe.getSource()) {
932                 fireFileRenamedEvent(getEnumOfListeners(), fe2Fire);
933             }
934         }
935
936         /**
937          * Implements FileChangeListener.fileAttributeChanged(FileAttributeEvent fe)
938          */

939         public void fileAttributeChanged(FileAttributeEvent fe) {
940             MasterFileObject eventFile = eventFileToMasterFileObject(fe);
941             FileAttributeEvent fe2Fire = new FileAttributeEvent(MasterFileObject.this, eventFile,
942                     fe.getName(), fe.getOldValue(), fe.getNewValue());
943             FileObject eventFileDelegate = eventFile.getDelegate().get();
944             FileObject meDelegate = MasterFileObject.this.getDelegate().get();
945             
946             if (eventFileDelegate == fe.getFile() && meDelegate == fe.getSource()) {
947                 fireFileAttributeChangedEvent(getEnumOfListeners(), fe2Fire);
948             }
949         }
950     }
951
952     private static ProvidedExtensions.DeleteHandler getDeleteHandler(File JavaDoc f) {
953         return getExtensions().getDeleteHandler(f);
954     }
955     
956     private static ProvidedExtensions getExtensions() {
957         return ((MasterFileSystem.StatusImpl)MasterFileSystem.getDefault().getStatus()).getExtensions();
958     }
959     
960     private static final class AtomicAction implements FileSystem.AtomicAction {
961         private int operation;
962         private final MasterFileObject hfoI;
963         private String JavaDoc nameI;
964         private String JavaDoc extI;
965         private FileObject targetI;
966         private FileLock fLockI;
967         private FileObject retVal;
968
969         private static final int CREATE_DATA_OP = 0;
970         private static final int CREATE_FOLDER_OP = 1;
971         private static final int CREATE_DATA_EXT_OP = 2;
972         private static final int COPY_OP = 3;
973         private static final int REFRESH_EXPECTED_OP = 4;
974         private static final int REFRESH_OP = 5;
975         private static final int DELETE_OP = 6;
976         private static final int MOVE_OP = 7;
977
978         private AtomicAction(final MasterFileObject hfo) {
979             this.hfoI = hfo;
980         }
981
982         private FileObject createFolder(final String JavaDoc name) throws IOException JavaDoc {
983             init(name);
984             operation = CREATE_FOLDER_OP;
985             // calls createFolder ()
986
getHFs().runAtomicAction(this);
987             return retVal;
988         }
989
990
991         FileObject createData(final String JavaDoc name) throws IOException JavaDoc {
992             init(name);
993             operation = CREATE_DATA_OP;
994             //calls createData
995
getHFs().runAtomicAction(this);
996             return retVal;
997         }
998
999         FileObject createData(final String JavaDoc name, final String JavaDoc ext) throws IOException JavaDoc {
1000            init(name, ext);
1001            operation = CREATE_DATA_EXT_OP;
1002            //calls createDataExt
1003
getHFs().runAtomicAction(this);
1004            return retVal;
1005        }
1006
1007        FileObject copy(FileObject target, String JavaDoc name, String JavaDoc ext) throws IOException JavaDoc {
1008            init(target, name, ext);
1009            operation = COPY_OP;
1010            //calls copy
1011
getHFs().runAtomicAction(this);
1012            return retVal;
1013        }
1014
1015        void delete(FileLock fLock) throws IOException JavaDoc {
1016            init(fLock, null, null, null);
1017            operation = DELETE_OP;
1018            //calls delete
1019
getHFs().runAtomicAction(this);
1020        }
1021
1022        FileObject move(FileLock lock, FileObject target, String JavaDoc name, String JavaDoc ext) throws IOException JavaDoc {
1023            init(lock, target, name, ext);
1024            operation = MOVE_OP;
1025            //calls move
1026
getHFs().runAtomicAction(this);
1027            return retVal;
1028        }
1029
1030        void refreshExpected() throws IOException JavaDoc {
1031            operation = REFRESH_EXPECTED_OP;
1032            //calls iRefreshExpected
1033
getHFs().runAtomicAction(this);
1034        }
1035
1036        void refresh() throws IOException JavaDoc {
1037            operation = REFRESH_OP;
1038            //calls iRefresh
1039
getHFs().runAtomicAction(this);
1040        }
1041
1042        public void run() throws IOException JavaDoc {
1043            hfoI.enterCriticalSection();
1044            try {
1045                switch (operation) {
1046                    case CREATE_FOLDER_OP:
1047                        createFolder();
1048                        break;
1049                    case CREATE_DATA_OP:
1050                        createData();
1051                        break;
1052                    case CREATE_DATA_EXT_OP:
1053                        createDataExt();
1054                        break;
1055                    case COPY_OP:
1056                        copy();
1057                        break;
1058                    case REFRESH_EXPECTED_OP:
1059                        iRefreshExpected();
1060                        break;
1061                    case REFRESH_OP:
1062                        iRefresh();
1063                        break;
1064                    case DELETE_OP:
1065                        delete();
1066                        break;
1067                    case MOVE_OP:
1068                        move();
1069                        break;
1070                }
1071            } finally {
1072                hfoI.finishCriticalSection();
1073            }
1074        }
1075
1076        private void init(FileLock fLock, final FileObject target, final String JavaDoc name, final String JavaDoc ext) {
1077            init(target, name, ext);
1078            this.fLockI = fLock;
1079        }
1080
1081        private void init(final FileObject target, final String JavaDoc name, final String JavaDoc ext) {
1082            init(name, ext);
1083            this.targetI = target;
1084        }
1085
1086        private void init(final String JavaDoc name, final String JavaDoc ext) {
1087            init(name);
1088            this.extI = ext;
1089        }
1090
1091        private void init(final String JavaDoc name) {
1092            this.nameI = name;
1093            retVal = null;
1094        }
1095
1096        // real implementation
1097
private void createFolder() throws IOException JavaDoc {
1098            FileObject deleg = getValidOrInvalid(hfoI.getDelegate().get(), hfoI);
1099            deleg.createFolder(nameI);
1100            retVal = getCache().getOrCreate(hfoI.getResource().getChild(nameI));
1101        }
1102
1103        private void createData() throws IOException JavaDoc {
1104            FileObject deleg = getValidOrInvalid(hfoI.getDelegate().get(), hfoI);
1105            deleg.createData(nameI);
1106            retVal = getCache().getOrCreate(hfoI.getResource().getChild(nameI));
1107        }
1108
1109        private void createDataExt() throws IOException JavaDoc {
1110            FileObject deleg = getValidOrInvalid(hfoI.getDelegate().get(), hfoI);
1111            deleg.createData(nameI, extI);
1112            retVal = getCache().getOrCreate(hfoI.getResource().getChild(nameI, extI));
1113        }
1114
1115        private void copy() throws IOException JavaDoc {
1116            FileObject deleg = getValidOrInvalid(hfoI.getDelegate().getPrefered(), hfoI);
1117            retVal = deleg.copy(targetI, nameI, extI);
1118        }
1119
1120        private void delete() throws IOException JavaDoc {
1121            FileObject deleg = getValidOrInvalid(hfoI.getDelegate().get(), hfoI);
1122            FileLock lck = Delegate.getLockForDelegate(fLockI, deleg);
1123            if (deleg instanceof BaseFileObj) {
1124                ((BaseFileObj)deleg).delete(lck,
1125                        MasterFileObject.getDeleteHandler(((BaseFileObj)deleg).getFileName().getFile()));
1126            } else {
1127                deleg.delete(lck);
1128            }
1129        }
1130
1131        private void move() throws IOException JavaDoc {
1132            ProvidedExtensions.IOHandler moveHandler = getMoveHandler();
1133            if (moveHandler != null) {
1134                //!!! NOT NICE: #73042 - Subversion support
1135
if (targetI instanceof MasterFileObject) {
1136                    BaseFileObj deleg = (BaseFileObj)getValidOrInvalid(hfoI.getDelegate().get(), hfoI);
1137                    FileLock lck = Delegate.getLockForDelegate(fLockI, deleg);
1138                    MasterFileObject targetMfo = (MasterFileObject)targetI;
1139                    FolderObj targetDeleg = (FolderObj)getValidOrInvalid(targetMfo.getDelegate().get(), targetMfo);
1140                    deleg.move(lck,targetDeleg,nameI, extI, moveHandler);
1141                    retVal = getCache().getOrCreate(targetMfo.getResource().getChild(nameI, extI));
1142                    FileUtil.copyAttributes(hfoI, retVal);
1143                } else {
1144                    moveHandler.handle();
1145                    hfoI.refresh(true);
1146                    //perfromance bottleneck to call refresh on folder
1147
//(especially for many files to be moved)
1148
targetI.refresh(true);
1149                    retVal = targetI.getFileObject(nameI, extI);
1150                    assert (retVal != null);
1151                    //!!! hfoI is already deleted when copyAttributes is invoked
1152
FileUtil.copyAttributes(hfoI, retVal);
1153                    return;
1154                }
1155            } else {
1156                retVal = hfoI.superMove(fLockI, targetI, nameI, extI);
1157            }
1158        }
1159        
1160        private ProvidedExtensions.IOHandler getMoveHandler() {
1161            ProvidedExtensions pe;
1162            pe = ((MasterFileSystem.StatusImpl)MasterFileSystem.getDefault().getStatus()).getExtensions();
1163            
1164            String JavaDoc fName = FileInfo.composeName(nameI, extI);
1165            File JavaDoc from = hfoI.getResource().getFile();
1166            File JavaDoc to = null;
1167            if (targetI instanceof MasterFileObject) {
1168                to = ((MasterFileObject)targetI).getResource().getChild(fName).getFile();
1169            } else {
1170                to = FileUtil.toFile(targetI);
1171            }
1172            return pe.getMoveHandler(from,to);
1173        }
1174        
1175        private void iRefreshExpected() {
1176            FileObject deleg = getValidOrInvalid(hfoI.getDelegate().get(), hfoI);
1177            if (deleg != null) deleg.refresh(true);
1178        }
1179
1180        private void iRefresh() {
1181            FileObject deleg = getValidOrInvalid(hfoI.getDelegate().get(), hfoI);
1182            if (deleg != null) deleg.refresh(false);
1183        }
1184        
1185        public boolean equals(Object JavaDoc obj) {
1186            return (obj instanceof AtomicAction);
1187        }
1188
1189        public int hashCode() {
1190            return AtomicAction.class.hashCode();
1191        }
1192        
1193    }
1194
1195}
1196
Popular Tags