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 170862
Collapse All | Expand All

(-)a/openide.filesystems/apichanges.xml (+17 lines)
Lines 46-51 Link Here
46
        <apidef name="filesystems">Filesystems API</apidef>
46
        <apidef name="filesystems">Filesystems API</apidef>
47
    </apidefs>
47
    </apidefs>
48
    <changes>
48
    <changes>
49
         <change id="recursive-listener">
50
            <api name="filesystems"/>
51
            <summary>Support for recursive listeners</summary>
52
            <version major="7" minor="24"/>
53
            <date day="1" month="9" year="2009"/>
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
                    One can register a recursive listener on a file object by
59
                    calling
60
                    <a href="@TOP@/org/openide/filesystems/FileObject.html#addRecursiveListener(org.openide.filesystems.FileChangeListener)">FileObject.addRecursiveListener(FileChangeListener)</a>.
61
                </p>
62
            </description>
63
            <class package="org.openide.filesystems" name="FileObject"/>
64
            <issue number="170862"/>
65
        </change>
49
         <change id="add-fallback-content-to-sfs">
66
         <change id="add-fallback-content-to-sfs">
50
            <api name="filesystems"/>
67
            <api name="filesystems"/>
51
            <summary>Allow modules to dynamically add/remove layer content</summary>
68
            <summary>Allow modules to dynamically add/remove layer content</summary>
(-)a/openide.filesystems/nbproject/project.properties (-1 / +1 lines)
Lines 44-47 Link Here
44
javadoc.main.page=org/openide/filesystems/doc-files/api.html
44
javadoc.main.page=org/openide/filesystems/doc-files/api.html
45
javadoc.arch=${basedir}/arch.xml
45
javadoc.arch=${basedir}/arch.xml
46
javadoc.apichanges=${basedir}/apichanges.xml
46
javadoc.apichanges=${basedir}/apichanges.xml
47
spec.version.base=7.23.0
47
spec.version.base=7.24.0
(-)a/openide.filesystems/src/org/openide/filesystems/ExternalUtil.java (-1 / +1 lines)
Lines 112-118 Link Here
112
        return orig;
112
        return orig;
113
    }
113
    }
114
114
115
    private static Logger LOG = Logger.getLogger("org.openide.filesystems"); // NOI18N
115
    final static Logger LOG = Logger.getLogger("org.openide.filesystems"); // NOI18N
116
    /** Logs a text.
116
    /** Logs a text.
117
     */
117
     */
118
    public static void log(String msg) {
118
    public static void log(String msg) {
(-)a/openide.filesystems/src/org/openide/filesystems/FileObject.java (+49 lines)
Lines 58-64 Link Here
58
import java.util.LinkedList;
58
import java.util.LinkedList;
59
import java.util.List;
59
import java.util.List;
60
import java.util.StringTokenizer;
60
import java.util.StringTokenizer;
61
import java.util.logging.Level;
61
import org.openide.util.Enumerations;
62
import org.openide.util.Enumerations;
63
import org.openide.util.Exceptions;
62
import org.openide.util.NbBundle;
64
import org.openide.util.NbBundle;
63
import org.openide.util.UserQuestionException;
65
import org.openide.util.UserQuestionException;
64
66
Lines 413-418 Link Here
413
    */
415
    */
414
    public abstract void removeFileChangeListener(FileChangeListener fcl);
416
    public abstract void removeFileChangeListener(FileChangeListener fcl);
415
417
418
419
    /** Adds a listener to this {@link FileObject} and all its children and
420
     * children or its children.
421
     * It is guaranteed that whenever a change
422
     * is made via the FileSystem API itself under this {@link FileObject}
423
     * that it is notified to the <code>fcl</code> listener. Whether external
424
     * changes (if they make sense) are detected and
425
     * notified depends on actual implementation. As some implementations may
426
     * need to perform non-trivial amount of work during initialization of
427
     * listeners, this methods can take long time. Usage of this method may
428
     * consume a lot of system resources and as such it shall be used with care.
429
     * Traditional {@link #addFileChangeListener(org.openide.filesystems.FileChangeListener)}
430
     * is definitely preferred variant.
431
     * <p class="nonnormative">
432
     * If you are running with the MasterFS module enabled, it guarantees
433
     * that for files backed with real {@link File}, the system initializes
434
     * itself to detect external changes on the whole subtree.
435
     * This requires non-trivial amount of work and especially on slow
436
     * disks (aka networks ones) may take a long time to add the listener
437
     * and also refresh the system when {@link FileObject#refresh()}
438
     * and especially {@link FileUtil#refreshAll()} is requested.
439
     * </p>
440
     *
441
     * @param fcl the listener to register
442
     * @since 7.24
443
     */
444
    public void addRecursiveListener(FileChangeListener fcl) {
445
        try {
446
            getFileSystem().addFileChangeListener(new RecursiveListener(this, fcl));
447
        } catch (FileStateInvalidException ex) {
448
            ExternalUtil.LOG.log(Level.FINE, "Cannot remove listener from " + this, ex);
449
        }
450
    }
451
452
    /** Removes listener previously added by {@link #addRecursiveListener(org.openide.filesystems.FileChangeListener)}
453
     *
454
     * @param fcl the listener to remove
455
     * @since 7.24
456
     */
457
    public void removeRecursiveListener(FileChangeListener fcl) {
458
        try {
459
            getFileSystem().removeFileChangeListener(new RecursiveListener(this, fcl));
460
        } catch (FileStateInvalidException ex) {
461
            ExternalUtil.LOG.log(Level.FINE, "Cannot remove listener from " + this, ex);
462
        }
463
    }
464
416
    /** Fire data creation event.
465
    /** Fire data creation event.
417
    * @param en listeners that should receive the event
466
    * @param en listeners that should receive the event
418
    * @param fe the event to fire in this object
467
    * @param fe the event to fire in this object
(-)33c1b2fcd188 (+127 lines)
Added Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.openide.filesystems;
41
42
import java.lang.ref.WeakReference;
43
44
/**
45
 *
46
 * @author Jaroslav Tulach <jtulach@netbeans.org>
47
 */
48
final class RecursiveListener extends WeakReference<FileObject>
49
implements FileChangeListener {
50
    private final FileChangeListener fcl;
51
52
    @Override
53
    public boolean equals(Object obj) {
54
        if (obj == null) {
55
            return false;
56
        }
57
        if (getClass() != obj.getClass()) {
58
            return false;
59
        }
60
        final RecursiveListener other = (RecursiveListener) obj;
61
        if (this.fcl != other.fcl && (this.fcl == null || !this.fcl.equals(other.fcl))) {
62
            return false;
63
        }
64
        final FileObject otherFo = other.get();
65
        final FileObject thisFo = this.get();
66
        if (thisFo != otherFo && (thisFo == null || !thisFo.equals(otherFo))) {
67
            return false;
68
        }
69
        return true;
70
    }
71
72
    @Override
73
    public int hashCode() {
74
        final FileObject thisFo = this.get();
75
        int hash = 3;
76
        hash = 37 * hash + (this.fcl != null ? this.fcl.hashCode() : 0);
77
        hash = 13 * hash + (thisFo != null ? thisFo.hashCode() : 0);
78
        return hash;
79
    }
80
81
    public RecursiveListener(FileObject source, FileChangeListener fcl) {
82
        super(source);
83
        this.fcl = fcl;
84
    }
85
86
    public void fileRenamed(FileRenameEvent fe) {
87
        FileObject thisFo = this.get();
88
        if (thisFo != null && FileUtil.isParentOf(thisFo, fe.getFile())) {
89
            fcl.fileRenamed(fe);
90
        }
91
    }
92
93
    public void fileFolderCreated(FileEvent fe) {
94
        FileObject thisFo = this.get();
95
        if (thisFo != null && FileUtil.isParentOf(thisFo, fe.getFile())) {
96
            fcl.fileFolderCreated(fe);
97
        }
98
    }
99
100
    public void fileDeleted(FileEvent fe) {
101
        FileObject thisFo = this.get();
102
        if (thisFo != null && FileUtil.isParentOf(thisFo, fe.getFile())) {
103
            fcl.fileDeleted(fe);
104
        }
105
    }
106
107
    public void fileDataCreated(FileEvent fe) {
108
        FileObject thisFo = this.get();
109
        if (thisFo != null && FileUtil.isParentOf(thisFo, fe.getFile())) {
110
            fcl.fileDataCreated(fe);
111
        }
112
    }
113
114
    public void fileChanged(FileEvent fe) {
115
        FileObject thisFo = this.get();
116
        if (thisFo != null && FileUtil.isParentOf(thisFo, fe.getFile())) {
117
            fcl.fileChanged(fe);
118
        }
119
    }
120
121
    public void fileAttributeChanged(FileAttributeEvent fe) {
122
        FileObject thisFo = this.get();
123
        if (thisFo != null && FileUtil.isParentOf(thisFo, fe.getFile())) {
124
            fcl.fileAttributeChanged(fe);
125
        }
126
    }
127
}
(-)a/openide.filesystems/test/unit/src/org/openide/filesystems/FileObjectTestHid.java (+98 lines)
Lines 1569-1574 Link Here
1569
            assertNotNull(child);        
1569
            assertNotNull(child);        
1570
        }
1570
        }
1571
    }
1571
    }
1572
1573
    public void testRecursiveListener() throws IOException {
1574
        checkSetUp();
1575
1576
        FileObject folder1 = getTestFolder1 (root);
1577
        /** delete first time*/
1578
        try {
1579
            FileObject obj = FileUtil.createData(folder1, "my/sub/children/children.java");
1580
            FileObject sub = obj.getParent().getParent();
1581
1582
            class L implements FileChangeListener {
1583
                StringBuilder sb = new StringBuilder();
1584
1585
                public void fileFolderCreated(FileEvent fe) {
1586
                    sb.append("FolderCreated");
1587
                }
1588
1589
                public void fileDataCreated(FileEvent fe) {
1590
                    sb.append("DataCreated");
1591
                }
1592
1593
                public void fileChanged(FileEvent fe) {
1594
                    sb.append("Changed");
1595
                }
1596
1597
                public void fileDeleted(FileEvent fe) {
1598
                    sb.append("Deleted");
1599
                }
1600
1601
                public void fileRenamed(FileRenameEvent fe) {
1602
                    sb.append("Renamed");
1603
                }
1604
1605
                public void fileAttributeChanged(FileAttributeEvent fe) {
1606
                    sb.append("AttributeChanged");
1607
                }
1608
1609
                public void assertMessages(String txt, String msg) {
1610
                    assertEquals(txt, msg, sb.toString());
1611
                    sb.setLength(0);
1612
                }
1613
            }
1614
            L recursive = new L();
1615
            L flat = new L();
1616
1617
            sub.addFileChangeListener(flat);
1618
            sub.addRecursiveListener(recursive);
1619
1620
            FileObject fo = obj.getParent().createData("sibling.java");
1621
1622
            flat.assertMessages("No messages in flat mode", "");
1623
            recursive.assertMessages("Creation", "DataCreated");
1624
1625
            fo.setAttribute("jarda", "hello");
1626
1627
            flat.assertMessages("No messages in flat mode", "");
1628
            recursive.assertMessages("attr", "AttributeChanged");
1629
1630
            final OutputStream os = fo.getOutputStream();
1631
            os.write(10);
1632
            os.close();
1633
1634
            flat.assertMessages("No messages in flat mode", "");
1635
            recursive.assertMessages("written", "Changed");
1636
1637
            fo.delete();
1638
1639
            flat.assertMessages("No messages in flat mode", "");
1640
            recursive.assertMessages("gone", "Deleted");
1641
1642
            sub.createFolder("testFolder");
1643
1644
            flat.assertMessages("Direct Folder notified", "FolderCreated");
1645
            recursive.assertMessages("Direct Folder notified", "FolderCreated");
1646
1647
            sub.getParent().createData("unimportant.txt");
1648
1649
            flat.assertMessages("No messages in flat mode", "");
1650
            recursive.assertMessages("No messages in recursive mode", "");
1651
1652
            sub.removeRecursiveListener(recursive);
1653
1654
            sub.createData("test.data");
1655
1656
            flat.assertMessages("Direct file notified", "DataCreated");
1657
            recursive.assertMessages("No longer active", "");
1658
1659
            WeakReference<L> ref = new WeakReference<L>(recursive);
1660
            recursive = null;
1661
            assertGC("Listener can be GCed", ref);
1662
1663
        } catch (IOException iex) {
1664
            if (fs.isReadOnly() || root.isReadOnly()) return;
1665
            throw iex;
1666
        } finally {
1667
        }
1668
    }
1669
1572
    
1670
    
1573
    /** Test of delete method, of class org.openide.filesystems.FileObject. */    
1671
    /** Test of delete method, of class org.openide.filesystems.FileObject. */    
1574
    public void testCreateDeleteFolderCreate () throws IOException {
1672
    public void testCreateDeleteFolderCreate () throws IOException {

Return to bug 170862