This Bugzilla instance is a read-only archive of historic NetBeans bug reports. To report a bug in NetBeans please follow the project's instructions for reporting issues.

View | Details | Raw Unified | Return to bug 181684
Collapse All | Expand All

(-)a/masterfs/apichanges.xml (+17 lines)
Lines 46-51 Link Here
46
        <apidef name="masterfs">MasterFileSystem API</apidef>
46
        <apidef name="masterfs">MasterFileSystem API</apidef>
47
    </apidefs>
47
    </apidefs>
48
    <changes>
48
    <changes>
49
        <change id="recursive-control">
50
            <api name="masterfs"/>
51
            <summary><code>ProvidedExtensions.refreshRecursively</code> was added.</summary>
52
            <version major="2" minor="23"/>
53
            <date day="14" month="4" year="2010"/>
54
            <author login="jtulach"/>
55
            <compatibility addition="yes" binary="compatible" source="compatible" semantic="compatible" deprecation="no" deletion="no" modification="no"/>
56
            <description>
57
                <p>
58
                    <code>ProvidedExtensions.refreshRecursively</code> allows
59
                    various version control providers to get better control
60
                    on behavior of recursive listener.
61
                </p>
62
            </description>
63
            <class package="org.netbeans.modules.masterfs.providers" name="ProvidedExtensions"/>
64
            <issue number="181684"/>
65
        </change>
49
        <change id="added-canWrite-friend-contract-for-versioning-systems">
66
        <change id="added-canWrite-friend-contract-for-versioning-systems">
50
            <api name="masterfs"/>
67
            <api name="masterfs"/>
51
            <summary><code>ProvidedExtensions.canWrite</code> was added.</summary>
68
            <summary><code>ProvidedExtensions.canWrite</code> was added.</summary>
(-)a/masterfs/manifest.mf (-1 / +1 lines)
Lines 1-7 Link Here
1
Manifest-Version: 1.0
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.netbeans.modules.masterfs/2
2
OpenIDE-Module: org.netbeans.modules.masterfs/2
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/masterfs/resources/Bundle.properties
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/masterfs/resources/Bundle.properties
4
OpenIDE-Module-Specification-Version: 2.22
4
OpenIDE-Module-Specification-Version: 2.23
5
AutoUpdate-Show-In-Client: false
5
AutoUpdate-Show-In-Client: false
6
AutoUpdate-Essential-Module: true
6
AutoUpdate-Essential-Module: true
7
7
(-)a/masterfs/src/org/netbeans/modules/masterfs/filebasedfs/fileobjects/FileObjectKeeper.java (-48 / +67 lines)
Lines 41-48 Link Here
41
41
42
import java.io.File;
42
import java.io.File;
43
import java.util.Collection;
43
import java.util.Collection;
44
import java.util.Enumeration;
45
import java.util.HashSet;
44
import java.util.HashSet;
45
import java.util.LinkedList;
46
import java.util.List;
46
import java.util.Set;
47
import java.util.Set;
47
import java.util.concurrent.Callable;
48
import java.util.concurrent.Callable;
48
import java.util.concurrent.CopyOnWriteArraySet;
49
import java.util.concurrent.CopyOnWriteArraySet;
Lines 61-67 Link Here
61
final class FileObjectKeeper implements FileChangeListener {
62
final class FileObjectKeeper implements FileChangeListener {
62
    private static final Logger LOG = Logger.getLogger(FileObjectKeeper.class.getName());
63
    private static final Logger LOG = Logger.getLogger(FileObjectKeeper.class.getName());
63
64
64
    private Set<FileObject> kept;
65
    private Set<FolderObj> kept;
65
    private Collection<FileChangeListener> listeners;
66
    private Collection<FileChangeListener> listeners;
66
    private final FolderObj root;
67
    private final FolderObj root;
67
    private long timeStamp;
68
    private long timeStamp;
Lines 94-140 Link Here
94
        }
95
        }
95
    }
96
    }
96
97
97
    public void init(long previous, FileObjectFactory factory, boolean expected) {
98
    public List<File> init(long previous, FileObjectFactory factory, boolean expected) {
98
        File file = root.getFileName().getFile();
99
        File file = root.getFileName().getFile();
99
        File[] arr = file.listFiles();
100
        LinkedList<File> arr = new LinkedList<File>();
100
        long ts = 0;
101
        long ts = root.getProvidedExtensions().refreshRecursively(file, previous, arr);
101
        if (arr != null) {
102
        for (File f : arr) {
102
            for (File f : arr) {
103
            if (f.isDirectory()) {
103
                if (f.isDirectory()) {
104
                continue;
104
                    continue;
105
            }
105
                }
106
            long lm = f.lastModified();
106
                long lm = f.lastModified();
107
            LOG.log(Level.FINE, "  check {0} for {1}", new Object[] { lm, f });
107
                LOG.log(Level.FINE, "  check {0} for {1}", new Object[] { lm, f });
108
            if (lm > ts) {
108
                if (lm > ts) {
109
                ts = lm;
109
                    ts = lm;
110
            }
110
                }
111
            if (lm > previous && factory != null) {
111
                if (lm > previous && factory != null) {
112
                final BaseFileObj prevFO = factory.getCachedOnly(f);
112
                    final BaseFileObj prevFO = factory.getCachedOnly(f);
113
                if (prevFO == null) {
113
                    if (prevFO == null) {
114
                    BaseFileObj who = factory.getValidFileObject(f, Caller.Others);
114
                        BaseFileObj who = factory.getValidFileObject(f, Caller.Others);
115
                    if (who != null) {
115
                        if (who != null) {
116
                        LOG.log(Level.FINE, "External change detected {0}", who);  //NOI18N
116
                            LOG.log(Level.FINE, "External change detected {0}", who);  //NOI18N
117
                        who.fireFileChangedEvent(expected);
117
                            who.fireFileChangedEvent(expected);
118
                        } else {
119
                            LOG.log(Level.FINE, "Cannot get valid FileObject. File probably removed: {0}", f);  //NOI18N
120
                        }
121
                    } else {
118
                    } else {
122
                        LOG.log(Level.FINE, "Do classical refresh for {0}", prevFO);  //NOI18N
119
                        LOG.log(Level.FINE, "Cannot get valid FileObject. File probably removed: {0}", f);  //NOI18N
123
                        prevFO.refresh(expected, true);
124
                    }
120
                    }
121
                } else {
122
                    LOG.log(Level.FINE, "Do classical refresh for {0}", prevFO);  //NOI18N
123
                    prevFO.refresh(expected, true);
125
                }
124
                }
126
            }
125
            }
127
        }
126
        }
128
        timeStamp = ts;
127
        timeStamp = ts;
129
        LOG.log(Level.FINE, "Testing {0}, time {1}", new Object[] { file, timeStamp });
128
        LOG.log(Level.FINE, "Testing {0}, time {1}", new Object[] { file, timeStamp });
129
        return arr;
130
    }
130
    }
131
131
132
    private void listenTo(FileObject fo, boolean add) {
132
    private void listenTo(FolderObj fo, boolean add, Collection<? super File> children) {
133
        if (add) {
133
        if (add) {
134
            fo.addFileChangeListener(this);
134
            fo.addFileChangeListener(this);
135
            if (fo instanceof FolderObj) {
135
            if (fo instanceof FolderObj) {
136
                FolderObj folder = (FolderObj)fo;
136
                FolderObj folder = (FolderObj)fo;
137
                folder.getKeeper();
137
                folder.getKeeper(children);
138
                folder.getChildren();
138
                kept.add(folder);
139
                kept.add(folder);
139
            }
140
            }
140
            LOG.log(Level.FINER, "Listening to {0}", fo);
141
            LOG.log(Level.FINER, "Listening to {0}", fo);
Lines 147-157 Link Here
147
    private void listenToAll(Callable<?> stop) {
148
    private void listenToAll(Callable<?> stop) {
148
        assert Thread.holdsLock(this);
149
        assert Thread.holdsLock(this);
149
        assert kept == null;
150
        assert kept == null;
150
        kept = new HashSet<FileObject>();
151
        kept = new HashSet<FolderObj>();
151
        listenTo(root, true);
152
        LinkedList<File> it = new LinkedList<File>();
152
        Enumeration<? extends FileObject> en = root.getChildren(true);
153
        listenTo(root, true, it);
153
        while (en.hasMoreElements()) {
154
        FileObjectFactory factory = null;
154
            FileObject fo = en.nextElement();
155
        for (;;) {
156
            File f = it.poll();
157
            if (f == null) {
158
                break;
159
            }
160
            if (factory == null) {
161
                factory = FileObjectFactory.getInstance(f);
162
            }
163
            FileObject fo = factory.getValidFileObject(f, Caller.Others);
155
            if (fo instanceof FolderObj) {
164
            if (fo instanceof FolderObj) {
156
                FolderObj obj = (FolderObj) fo;
165
                FolderObj obj = (FolderObj) fo;
157
                Object shallStop = null;
166
                Object shallStop = null;
Lines 166-172 Link Here
166
                    LOG.log(Level.INFO, "addRecursiveListener to {0} interrupted", root); // NOI18N
175
                    LOG.log(Level.INFO, "addRecursiveListener to {0} interrupted", root); // NOI18N
167
                    return;
176
                    return;
168
                }
177
                }
169
                listenTo(obj, true);
178
                listenTo(obj, true, it);
170
            }
179
            }
171
        }
180
        }
172
    }
181
    }
Lines 174-184 Link Here
174
    private void listenNoMore() {
183
    private void listenNoMore() {
175
        assert Thread.holdsLock(this);
184
        assert Thread.holdsLock(this);
176
185
177
        listenTo(root, false);
186
        listenTo(root, false, null);
178
        Set<FileObject> k = kept;
187
        Set<FolderObj> k = kept;
179
        if (k != null) {
188
        if (k != null) {
180
            for (FileObject fo : k) {
189
            for (FolderObj fo : k) {
181
                listenTo(fo, false);
190
                listenTo(fo, false, null);
182
            }
191
            }
183
            kept = null;
192
            kept = null;
184
        }
193
        }
Lines 187-201 Link Here
187
    @Override
196
    @Override
188
    public void fileFolderCreated(FileEvent fe) {
197
    public void fileFolderCreated(FileEvent fe) {
189
        Collection<FileChangeListener> arr = listeners;
198
        Collection<FileChangeListener> arr = listeners;
190
        final FileObject f = fe.getFile();
199
        final FileObject folder = fe.getFile();
191
        if (f instanceof FolderObj) {
200
        if (folder instanceof FolderObj) {
201
            FolderObj obj = (FolderObj)folder;
192
            synchronized (this) {
202
            synchronized (this) {
193
                listenTo(f, true);
203
                LinkedList<File> it = new LinkedList<File>();
194
                Enumeration<? extends FileObject> en = f.getChildren(true);
204
                listenTo(obj, true, it);
195
                while (en.hasMoreElements()) {
205
                FileObjectFactory factory = null;
196
                    FileObject fo = en.nextElement();
206
                for (;;) {
207
                    File f = it.poll();
208
                    if (f == null) {
209
                        break;
210
                    }
211
                    if (factory == null) {
212
                        factory = FileObjectFactory.getInstance(f);
213
                    }
214
                    FileObject fo = factory.getValidFileObject(f, Caller.Others);
197
                    if (fo instanceof FolderObj) {
215
                    if (fo instanceof FolderObj) {
198
                        listenTo(fo, true);
216
                        listenTo((FolderObj)fo, true, it);
199
                    }
217
                    }
200
                }
218
                }
201
            }
219
            }
Lines 240-250 Link Here
240
        }
258
        }
241
259
242
        if (f instanceof FolderObj) {
260
        if (f instanceof FolderObj) {
261
            FolderObj obj = (FolderObj)f;
243
            synchronized (this) {
262
            synchronized (this) {
244
                if (kept != null) {
263
                if (kept != null) {
245
                    kept.remove(f);
264
                    kept.remove(obj);
246
                }
265
                }
247
                listenTo(f, false);
266
                listenTo(obj, false, null);
248
            }
267
            }
249
        }
268
        }
250
        if (arr == null) {
269
        if (arr == null) {
(-)a/masterfs/src/org/netbeans/modules/masterfs/filebasedfs/fileobjects/FolderObj.java (-5 / +11 lines)
Lines 48-53 Link Here
48
import java.io.OutputStream;
48
import java.io.OutputStream;
49
import java.io.SyncFailedException;
49
import java.io.SyncFailedException;
50
import java.util.ArrayList;
50
import java.util.ArrayList;
51
import java.util.Collection;
51
import java.util.HashSet;
52
import java.util.HashSet;
52
import java.util.LinkedList;
53
import java.util.LinkedList;
53
import java.util.List;
54
import java.util.List;
Lines 70-76 Link Here
70
import org.openide.filesystems.FileChangeListener;
71
import org.openide.filesystems.FileChangeListener;
71
import org.openide.filesystems.FileLock;
72
import org.openide.filesystems.FileLock;
72
import org.openide.filesystems.FileObject;
73
import org.openide.filesystems.FileObject;
73
import org.openide.util.Exceptions;
74
import org.openide.util.Mutex;
74
import org.openide.util.Mutex;
75
75
76
/**
76
/**
Lines 520-541 Link Here
520
        return folderChildren;
520
        return folderChildren;
521
    }
521
    }
522
522
523
    synchronized FileObjectKeeper getKeeper() {
523
    synchronized FileObjectKeeper getKeeper(Collection<? super File> arr) {
524
        if (keeper == null) {
524
        if (keeper == null) {
525
            keeper = new FileObjectKeeper(this);
525
            keeper = new FileObjectKeeper(this);
526
            keeper.init(-1, null, false);
526
            List<File> ch = keeper.init(-1, null, false);
527
            if (arr != null) {
528
                arr.addAll(ch);
529
            }
530
        } else if (arr != null) {
531
            List<File> ch = keeper.init(keeper.childrenLastModified(), null, false);
532
            arr.addAll(ch);
527
        }
533
        }
528
        return keeper;
534
        return keeper;
529
    }
535
    }
530
536
531
    @Override
537
    @Override
532
    public final void addRecursiveListener(FileChangeListener fcl) {
538
    public final void addRecursiveListener(FileChangeListener fcl) {
533
        getKeeper().addRecursiveListener(fcl);
539
        getKeeper(null).addRecursiveListener(fcl);
534
    }
540
    }
535
541
536
    @Override
542
    @Override
537
    public final void removeRecursiveListener(FileChangeListener fcl) {
543
    public final void removeRecursiveListener(FileChangeListener fcl) {
538
        getKeeper().removeRecursiveListener(fcl);
544
        getKeeper(null).removeRecursiveListener(fcl);
539
    }
545
    }
540
546
541
547
(-)a/masterfs/src/org/netbeans/modules/masterfs/providers/ProvidedExtensions.java (+24 lines)
Lines 43-48 Link Here
43
43
44
import java.io.File;
44
import java.io.File;
45
import java.io.IOException;
45
import java.io.IOException;
46
import java.util.Arrays;
47
import java.util.List;
46
import org.openide.filesystems.FileObject;
48
import org.openide.filesystems.FileObject;
47
49
48
/**
50
/**
Lines 187-190 Link Here
187
    public Object getAttribute(File file, String attrName) {
189
    public Object getAttribute(File file, String attrName) {
188
        return null;
190
        return null;
189
    }
191
    }
192
193
    /** Allows versioning system to exclude some children from recursive
194
     * listening check. Also notifies the versioning whenever a refresh
195
     * is required and allows the versiniong to provide special timestamp
196
     * for a directory.
197
     *
198
     * @param dir the directory to check timestamp for
199
     * @param lastTimeStamp the previously known timestamp or -1
200
     * @param children add children that shall be interated into this array
201
     * @return the timestamp that shall represent this directory, it will
202
     *   be compared with timestamps of all children and the newest
203
     *   one will be kept and next time passed as lastTimeStamp. Return
204
     *   0 if the directory does not have any special timestamp
205
     * @since 2.23
206
     */
207
    public long refreshRecursively(File dir, long lastTimeStamp, List<? super File> children) {
208
        final File[] arr = dir.listFiles();
209
        if (arr != null) {
210
            children.addAll(Arrays.asList(arr));
211
        }
212
        return 0;
213
    }
190
}
214
}

Return to bug 181684