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

(-)a/masterfs/nbproject/project.properties (-1 / +1 lines)
Lines 59-62 Link Here
59
    **/SlowRefreshAndPriorityIOTest.class,\
59
    **/SlowRefreshAndPriorityIOTest.class,\
60
    **/SlowRefreshSuspendableTest.class,\
60
    **/SlowRefreshSuspendableTest.class,\
61
    **/StatFilesTest.class
61
    **/StatFilesTest.class
62
spec.version.base=2.51.0
62
spec.version.base=2.52
(-)a/masterfs/nbproject/project.xml (-1 / +1 lines)
Lines 87-93 Link Here
87
                    <build-prerequisite/>
87
                    <build-prerequisite/>
88
                    <compile-dependency/>
88
                    <compile-dependency/>
89
                    <run-dependency>
89
                    <run-dependency>
90
                        <specification-version>8.0</specification-version>
90
                        <specification-version>8.10</specification-version>
91
                    </run-dependency>
91
                    </run-dependency>
92
                </dependency>
92
                </dependency>
93
            </module-dependencies>
93
            </module-dependencies>
(-)a/masterfs/src/org/netbeans/modules/masterfs/filebasedfs/fileobjects/BaseFileObj.java (+83 lines)
Lines 62-67 Link Here
62
import java.nio.file.Files;
62
import java.nio.file.Files;
63
import java.nio.file.Path;
63
import java.nio.file.Path;
64
import java.nio.file.Paths;
64
import java.nio.file.Paths;
65
import java.security.AccessController;
66
import java.security.PrivilegedActionException;
67
import java.security.PrivilegedExceptionAction;
65
import java.util.ArrayDeque;
68
import java.util.ArrayDeque;
66
import java.util.Arrays;
69
import java.util.Arrays;
67
import java.util.Date;
70
import java.util.Date;
Lines 1084-1089 Link Here
1084
    FolderObj getExistingParent() {         
1087
    FolderObj getExistingParent() {         
1085
        return getExistingParentFor(getFileName().getFile(), getFactory());
1088
        return getExistingParentFor(getFileName().getFile(), getFactory());
1086
    }
1089
    }
1090
1091
    /**
1092
     * Get {@link Path} object for this BaseFileObj.
1093
     */
1094
    private Path getNativePath() throws IOException {
1095
        File file = getFileName().getFile();
1096
        final Path path;
1097
        try {
1098
            path = file.toPath();
1099
        } catch (RuntimeException e) {
1100
            throw new IOException("Cannot get Path for " + this, e);    //NOI18N
1101
        }
1102
        return path;
1103
    }
1104
1105
    @Override
1106
    public boolean isSymbolicLink() throws IOException {
1107
        Path p = getNativePath();
1108
        return Files.isSymbolicLink(p);
1109
    }
1110
1111
    @Override
1112
    public FileObject readSymbolicLink() throws IOException {
1113
        final Path path = getNativePath();
1114
        try {
1115
            return AccessController.doPrivileged(
1116
                    new PrivilegedExceptionAction<FileObject>() {
1117
1118
                        @Override
1119
                        public FileObject run() throws Exception {
1120
                            Path target = Files.readSymbolicLink(path);
1121
                            Path absoluteTarget = target.isAbsolute()
1122
                                ? target
1123
                                : path.getParent().resolve(target);
1124
                            File file = absoluteTarget.toFile();
1125
                            File normFile = FileUtil.normalizeFile(file);
1126
                            return FileBasedFileSystem.getFileObject(normFile);
1127
                        }
1128
                    });
1129
        } catch (PrivilegedActionException ex) {
1130
            throw new IOException(ex);
1131
        }
1132
    }
1133
1134
    @Override
1135
    public String readSymbolicLinkPath() throws IOException {
1136
        final Path path = getNativePath();
1137
        try {
1138
            return AccessController.doPrivileged(
1139
                    new PrivilegedExceptionAction<String>() {
1140
1141
                        @Override
1142
                        public String run() throws Exception {
1143
                            Path target = Files.readSymbolicLink(path);
1144
                            return target.toString();
1145
                        }
1146
                    });
1147
        } catch (PrivilegedActionException ex) {
1148
            throw new IOException(ex);
1149
        }
1150
    }
1151
1152
    @Override
1153
    public FileObject getCanonicalFileObject() throws IOException {
1154
        final Path path = getNativePath();
1155
        try {
1156
            return AccessController.doPrivileged(
1157
                    new PrivilegedExceptionAction<FileObject>() {
1158
1159
                        @Override
1160
                        public FileObject run() throws Exception {
1161
                            Path realPath = path.toRealPath();
1162
                            File realFile = realPath.toFile();
1163
                            return FileBasedFileSystem.getFileObject(realFile);
1164
                        }
1165
                    });
1166
        } catch (PrivilegedActionException ex) {
1167
            throw new IOException(ex);
1168
        }
1169
    }
1087
    
1170
    
1088
    private static class FileEventImpl extends FileEvent implements Enumeration<FileEvent> {
1171
    private static class FileEventImpl extends FileEvent implements Enumeration<FileEvent> {
1089
        static {
1172
        static {
(-)a/masterfs/test/unit/src/org/netbeans/modules/masterfs/filebasedfs/fileobjects/FileObjSymlinkTest.java (+285 lines)
Line 0 Link Here
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2013 Oracle and/or its affiliates. All rights reserved.
5
 *
6
 * Oracle and Java are registered trademarks of Oracle and/or its affiliates.
7
 * Other names may be trademarks of their respective owners.
8
 *
9
 * The contents of this file are subject to the terms of either the GNU
10
 * General Public License Version 2 only ("GPL") or the Common
11
 * Development and Distribution License("CDDL") (collectively, the
12
 * "License"). You may not use this file except in compliance with the
13
 * License. You can obtain a copy of the License at
14
 * http://www.netbeans.org/cddl-gplv2.html
15
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
16
 * specific language governing permissions and limitations under the
17
 * License.  When distributing the software, include this License Header
18
 * Notice in each file and include the License file at
19
 * nbbuild/licenses/CDDL-GPL-2-CP.  Oracle designates this
20
 * particular file as subject to the "Classpath" exception as provided
21
 * by Oracle in the GPL Version 2 section of the License file that
22
 * accompanied this code. If applicable, add the following below the
23
 * License Header, with the fields enclosed by brackets [] replaced by
24
 * your own identifying information:
25
 * "Portions Copyrighted [year] [name of copyright owner]"
26
 *
27
 * If you wish your version of this file to be governed by only the CDDL
28
 * or only the GPL Version 2, indicate your decision by adding
29
 * "[Contributor] elects to include this software in this distribution
30
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
31
 * single choice of license, a recipient has the option to distribute
32
 * your version of this file under either the CDDL, the GPL Version 2 or
33
 * to extend the choice of license to its licensees as provided above.
34
 * However, if you add GPL Version 2 code and therefore, elected the GPL
35
 * Version 2 license, then the option applies only if the new code is
36
 * made subject to such option by the copyright holder.
37
 *
38
 * Contributor(s):
39
 *
40
 * Portions Copyrighted 2013 Sun Microsystems, Inc.
41
 */
42
package org.netbeans.modules.masterfs.filebasedfs.fileobjects;
43
44
import java.io.File;
45
import java.io.IOException;
46
import java.nio.file.Files;
47
import java.nio.file.Path;
48
import java.nio.file.Paths;
49
import org.netbeans.junit.NbTestCase;
50
import org.openide.filesystems.FileObject;
51
import org.openide.filesystems.FileUtil;
52
53
/**
54
 * Test support for detection and reading of symbolic links.
55
 *
56
 * @author jhavlin
57
 */
58
public class FileObjSymlinkTest extends NbTestCase {
59
60
    public FileObjSymlinkTest(String name) {
61
        super(name);
62
    }
63
64
    @Override
65
    protected void setUp() throws Exception {
66
        deleteSymlinks(getWorkDir());
67
        clearWorkDir();
68
    }
69
70
    public void testIsSymbolicLink() throws IOException {
71
        if (!checkSymlinksSupported()) {
72
            return;
73
        }
74
        File dir = getWorkDir();
75
        Path p = dir.toPath();
76
        Path data = p.resolve("data.dat");
77
        Path link = p.resolve("link.lk");
78
        data.toFile().createNewFile();
79
        Files.createSymbolicLink(link, data);
80
        FileObject dirFO = FileUtil.toFileObject(dir);
81
        dirFO.refresh();
82
        FileObject dataFO = dirFO.getFileObject("data.dat");
83
        FileObject linkFO = dirFO.getFileObject("link.lk");
84
        assertFalse(dataFO.isSymbolicLink());
85
        assertTrue(linkFO.isSymbolicLink());
86
    }
87
88
    /**
89
     * Test isRecursiveSymbolicLink method. Use this folder tree:
90
     * <pre>
91
     * - workdir
92
     *   - a
93
     *     - b
94
     *       - c (symlink to a)
95
     *       - d (symlink to e)
96
     *   - e
97
     * </pre>
98
     *
99
     * @throws java.io.IOException
100
     */
101
    public void testIsRecursiveSymbolicLink() throws IOException {
102
        if (!checkSymlinksSupported()) {
103
            return;
104
        }
105
        File dir = getWorkDir();
106
        File a = new File(dir, "a");
107
        File b = new File(a, "b");
108
        File c = new File(b, "c");
109
        File d = new File(b, "d");
110
        File e = new File(dir, "e");
111
        b.mkdirs();
112
        e.mkdirs();
113
        Files.createSymbolicLink(c.toPath(), a.toPath());
114
        Files.createSymbolicLink(d.toPath(), e.toPath());
115
        FileObject dirFO = FileUtil.toFileObject(dir);
116
        dirFO.refresh();
117
        FileObject cFO = dirFO.getFileObject("a/b/c");
118
        FileObject dFO = dirFO.getFileObject("a/b/d");
119
        assertTrue(FileUtil.isRecursiveSymbolicLink(cFO));
120
        assertFalse(FileUtil.isRecursiveSymbolicLink(dFO));
121
        assertFalse(FileUtil.isRecursiveSymbolicLink(dirFO));
122
    }
123
124
    /**
125
     * Test isRecursiveSymbolicLink method. Use this folder tree:
126
     * <pre>
127
     * - workdir
128
     *   - a
129
     *     - b
130
     *       - c (symlink to d)
131
     *   - d (symlink to a)
132
     * </pre>
133
     *
134
     * @throws java.io.IOException
135
     */
136
    public void testIsRecursiveSymbolicLinkIndirect() throws IOException {
137
        if (!checkSymlinksSupported()) {
138
            return;
139
        }
140
        File dir = getWorkDir();
141
        File a = new File(dir, "a");
142
        File b = new File(a, "b");
143
        File c = new File(b, "c");
144
        File d = new File(dir, "d");
145
        b.mkdirs();
146
        Files.createSymbolicLink(d.toPath(), a.toPath());
147
        Files.createSymbolicLink(c.toPath(), d.toPath());
148
        FileObject dirFO = FileUtil.toFileObject(dir);
149
        FileObject cFO = dirFO.getFileObject("a/b/c");
150
        assertTrue(FileUtil.isRecursiveSymbolicLink(cFO));
151
    }
152
153
    public void testReadSymbolicLinkAbsolute() throws IOException {
154
        if (!checkSymlinksSupported()) {
155
            return;
156
        }
157
        File dir = getWorkDir();
158
        File data = new File(dir, "data.dat");
159
        File link = new File(dir, "link.lnk");
160
        data.createNewFile();
161
        Files.createSymbolicLink(link.toPath(), data.toPath());
162
        FileObject linkFO = FileUtil.toFileObject(link);
163
        FileObject dataFO = linkFO.readSymbolicLink();
164
        assertNotSame(linkFO, dataFO);
165
        assertNotNull(dataFO);
166
        assertEquals("data.dat", dataFO.getNameExt());
167
    }
168
169
    public void testReadSymbolicLinkRelative() throws IOException {
170
        if (!checkSymlinksSupported()) {
171
            return;
172
        }
173
        File dir = getWorkDir();
174
        File folder = new File(dir, "folder");
175
        File link = new File(dir, "link");
176
        folder.mkdir();
177
        Path lp = Files.createSymbolicLink(link.toPath(), Paths.get("folder"));
178
        assertNotNull(lp);
179
        FileObject linkFO = FileUtil.toFileObject(link);
180
        assertNotNull(linkFO);
181
        FileObject dataFO = linkFO.readSymbolicLink();
182
        assertNotSame(linkFO, dataFO);
183
        assertNotNull(dataFO);
184
        assertEquals("folder", dataFO.getNameExt());
185
    }
186
187
    public void testReadSymbolicLinkPath() throws IOException {
188
        if (!checkSymlinksSupported()) {
189
            return;
190
        }
191
        File dir = getWorkDir();
192
        File data = new File(dir, "data.dat");
193
        File link = new File(dir, "link.lnk");
194
        data.createNewFile();
195
        Files.createSymbolicLink(link.toPath(), data.toPath());
196
        FileObject linkFO = FileUtil.toFileObject(link);
197
        assertTrue(linkFO.readSymbolicLinkPath().endsWith("data.dat"));
198
    }
199
200
    /**
201
     * Test getCanonicalFileObject method.
202
     *
203
     * Use this directory tree:
204
     * <pre>
205
     * - workdir
206
     *   - a
207
     *     - data.dat
208
     *   - b
209
     *     - link.lnk (symlink to data.dat)
210
     *   - c
211
     *     - link2.lnk (symlink to link.link)
212
     *   - d
213
     *     - folderLink (symlink to c)
214
     * </pre>
215
     * @throws java.io.IOException
216
     */
217
    public void testGetRealFileObject() throws IOException {
218
        if (!checkSymlinksSupported()) {
219
            return;
220
        }
221
        File dir = getWorkDir();
222
        File a = new File(dir, "a");
223
        File dataDat = new File(a, "data.dat");
224
        File b = new File(dir, "b");
225
        File linkLnk = new File(b, "link.lnk");
226
        File c = new File(dir, "c");
227
        File link2Lnk = new File(c, "link2.lnk");
228
        File d = new File(dir, "d");
229
        File folderLink = new File(d, "folderLink");
230
        a.mkdir();
231
        dataDat.createNewFile();
232
        b.mkdir();
233
        Files.createSymbolicLink(linkLnk.toPath(), dataDat.toPath());
234
        c.mkdir();
235
        Files.createSymbolicLink(link2Lnk.toPath(), linkLnk.toPath());
236
        d.mkdir();
237
        Files.createSymbolicLink(folderLink.toPath(), c.toPath());
238
        FileObject dirFO = FileUtil.toFileObject(dir);
239
        dirFO.refresh();
240
        FileObject fo = dirFO.getFileObject("d/folderLink/link2.lnk");
241
        assertNotNull(fo);
242
        FileObject realFO = fo.getCanonicalFileObject();
243
        assertNotNull(realFO);
244
        assertTrue(realFO.getPath().endsWith("a/data.dat"));
245
    }
246
247
    /**
248
     * Recursively delete all symlinks in a directory.
249
     */
250
    private void deleteSymlinks(File root) {
251
        for (File f : root.listFiles()) {
252
            if (Files.isSymbolicLink(f.toPath())) {
253
                f.delete();
254
            } else if (f.isDirectory()) {
255
                deleteSymlinks(f);
256
            }
257
        }
258
    }
259
260
    private boolean checkSymlinksSupported() {
261
        File dir;
262
        try {
263
            dir = getWorkDir();
264
        } catch (IOException ex) {
265
            printSkipping();
266
            return false;
267
        }
268
        File a = new File(dir, "a");
269
        try {
270
            File lk = new File(dir, "lk");
271
            Files.createSymbolicLink(lk.toPath(), a.toPath());
272
            lk.delete();
273
            return true;
274
        } catch (RuntimeException e) {
275
        } catch (IOException ex) {
276
        }
277
        printSkipping();
278
        return false;
279
    }
280
281
    private void printSkipping() {
282
        System.out.println(
283
                "Symbolic links are not supported, skipping test " + getName());
284
    }
285
}
(-)a/openide.filesystems/apichanges.xml (+30 lines)
Lines 49-54 Link Here
49
        <apidef name="filesystems">Filesystems API</apidef>
49
        <apidef name="filesystems">Filesystems API</apidef>
50
    </apidefs>
50
    </apidefs>
51
    <changes>
51
    <changes>
52
        <change id="FileObject.symbolicLinks">
53
            <api name="filesystems"/>
54
            <summary>Support detection and reading of symbolic links.</summary>
55
            <version major="9" minor="4"/>
56
            <date year="2014" month="11" day="27"/>
57
            <author login="jhavlin"/>
58
            <compatibility addition="yes"/>
59
            <description>
60
                <p>
61
                    Add methods to <code>FileObject</code> for handling of
62
                    symbolic links:
63
                </p>
64
                <ul>
65
                    <li><code>isSymbolicLink()</code></li>
66
                    <li><code>readSymbolicLink()</code></li>
67
                    <li><code>readSymbolicLinkPath()</code></li>
68
                    <li><code>getCanonicalFileObject()</code></li>
69
                </ul>
70
                <p>
71
                    Add utility method to <code>FileUtil</code> for dealing with
72
                    recursive symbolic links.
73
                </p>
74
                <ul>
75
                    <li><code>isRecursiveSymbolicLink()</code></li>
76
                </ul>
77
            </description>
78
            <class package="org.openide.filesystems" name="FileObject"/>
79
            <class package="org.openide.filesystems" name="FileUtil"/>
80
            <issue number="237882"/>
81
        </change>
52
        <change id="FileLock.closeable">
82
        <change id="FileLock.closeable">
53
            <api name="filesystems"/>
83
            <api name="filesystems"/>
54
            <summary>FileLock implements AutoCloseable</summary>
84
            <summary>FileLock implements AutoCloseable</summary>
(-)a/openide.filesystems/manifest.mf (-1 / +1 lines)
Lines 2-7 Link Here
2
OpenIDE-Module: org.openide.filesystems
2
OpenIDE-Module: org.openide.filesystems
3
OpenIDE-Module-Localizing-Bundle: org/openide/filesystems/Bundle.properties
3
OpenIDE-Module-Localizing-Bundle: org/openide/filesystems/Bundle.properties
4
OpenIDE-Module-Layer: org/openide/filesystems/resources/layer.xml
4
OpenIDE-Module-Layer: org/openide/filesystems/resources/layer.xml
5
OpenIDE-Module-Specification-Version: 9.3
5
OpenIDE-Module-Specification-Version: 9.4
6
6
7
7
(-)a/openide.filesystems/src/org/openide/filesystems/AbstractFileSystem.java (+58 lines)
Lines 659-664 Link Here
659
        public void markUnimportant(String name);
659
        public void markUnimportant(String name);
660
    }
660
    }
661
661
662
    /**
663
     * Information about files related to symbolic links.
664
     */
665
    @SuppressWarnings("PublicInnerClass")
666
    public interface SymlinkInfo extends Serializable {
667
668
        /**
669
         * Check whether a file represents a symbolic link.
670
         *
671
         * @param name Name of the file.
672
         *
673
         * @return True if this file represents a symbolic link, false
674
         * otherwise.
675
         * @throws java.io.IOException If some I/O problem occurs.
676
         * @since openide.filesystem/9.4
677
         *
678
         * @see #readSymbolicLink(java.lang.String)
679
         * @see #getCanonicalName(java.lang.String)
680
         */
681
        boolean isSymbolicLink(String name) throws IOException;
682
683
        /**
684
         * Read symbolic link.
685
         *
686
         * If the file represents a symbolic link, return its target path.
687
         * Otherwise the return value is undefined, or
688
         * {@link IllegalArgumentException} can be thrown.
689
         *
690
         * This method does not perform any normalization. If the target of
691
         * symbolic link is defined using relative path, this relative path will
692
         * be returned.
693
         *
694
         * @param name Name of the file.
695
         *
696
         * @throws java.io.IOException If some I/O problem occurs.
697
         * @since openide.filesystem/9.4
698
         *
699
         * @return Target of the symbolic link (as absolute or relative path),
700
         * or some undefined value if {@code name} does not represent symbolic
701
         * link.
702
         *
703
         * @see #isSymbolicLink(java.lang.String)
704
         */
705
        String readSymbolicLink(String name) throws IOException;
706
707
        /**
708
         * Get canonical file name (resolve all symbolic links).
709
         *
710
         * @param name Name of the file.
711
         *
712
         * @return Path that represents the same file as {@code name} and
713
         * where all symbolic links are resolved.
714
         * @throws java.io.IOException If some I/O problem occurs.
715
         * @since openide.filesystem/9.4
716
         */
717
        String getCanonicalName(String name) throws IOException;
718
    }
719
662
    /** Handle attributes of files.
720
    /** Handle attributes of files.
663
    */
721
    */
664
    public interface Attr extends Serializable {
722
    public interface Attr extends Serializable {
(-)a/openide.filesystems/src/org/openide/filesystems/FileObject.java (-2 / +73 lines)
Lines 902-909 Link Here
902
            public FileObject process(FileObject fo, Collection<FileObject> toAdd) {
902
            public FileObject process(FileObject fo, Collection<FileObject> toAdd) {
903
                if (rec && fo.isFolder()) {
903
                if (rec && fo.isFolder()) {
904
                    for (FileObject child : fo.getChildren()) {
904
                    for (FileObject child : fo.getChildren()) {
905
                        if (!FileUtil.isRecursiveSymlink(child)) { // #218795
905
                        try {
906
                            toAdd.add(child);
906
                            if (!FileUtil.isRecursiveSymbolicLink(child)) { // #218795
907
                                toAdd.add(child);
908
                            }
909
                        } catch (IOException ex) {
910
                            ExternalUtil.LOG.log(Level.INFO, null, ex);
907
                        }
911
                        }
908
                    }
912
                    }
909
                }
913
                }
Lines 1253-1258 Link Here
1253
        return false;
1257
        return false;
1254
    }
1258
    }
1255
1259
1260
    /**
1261
     * Check whether this FileObject is a symbolic link.
1262
     *
1263
     * The default implementation returns false, but on filesystems that support
1264
     * symbolic links this method should be overriden.
1265
     *
1266
     * @return True if this FileObject represents a symbolic link, false
1267
     * otherwise.
1268
     * @throws java.io.IOException If some I/O problem occurs.
1269
     * @since openide.filesystem/9.4
1270
     */
1271
    public boolean isSymbolicLink() throws IOException {
1272
        return false;
1273
    }
1274
1275
    /**
1276
     * Read symbolic link.
1277
     *
1278
     * If this FileObject represents a symbolic link, return a FileObject it
1279
     * refers to, or null if the referred file or directory does not exist. If
1280
     * this FileObject doesn't represent a symbolic link, the return value is
1281
     * undefined.
1282
     *
1283
     * The default implementation returns null, but on filesystems that support
1284
     * symbolic links this method should be overriden.
1285
     *
1286
     * @return The referred FileObject, or null if it is not available.
1287
     * @throws java.io.IOException If some I/O problem occurs.
1288
     * @since openide.filesystem/9.4
1289
     */
1290
    public FileObject readSymbolicLink() throws IOException {
1291
        return null;
1292
    }
1293
1294
    /**
1295
     * Read symbolic link path.
1296
     *
1297
     * If this FileObject represents a symbolic link, return the path it refers
1298
     * to, which can be absolute or relative. If this FileObject doesn't
1299
     * represent a symbolic link, the return value is undefined.
1300
     *
1301
     * The default implementation returns this FileObject's path, but on
1302
     * filesystems that support symbolic links this method should be overriden.
1303
     *
1304
     * @return The referred FileObject path.
1305
     * @throws java.io.IOException If some I/O problem occurs.
1306
     * @since openide.filesystem/9.4
1307
     */
1308
    public String readSymbolicLinkPath() throws IOException {
1309
        return this.getPath();
1310
    }
1311
1312
    /**
1313
     * Return a FileObject with path where all symbolic links are resolved.
1314
     *
1315
     * The default implementation returns this object, but on filesystems that
1316
     * support symbolic links this method should be overriden.
1317
     *
1318
     * @return The FileObject with path where all symlinks are resolved, or null
1319
     * if it doesn't exist.
1320
     * @throws java.io.IOException If some I/O problem occurs.
1321
     * @since openide.filesystem/9.4
1322
     */
1323
    public FileObject getCanonicalFileObject() throws IOException {
1324
        return this;
1325
    }
1326
1256
    /** Listeners registered from MultiFileObject are considered as priority
1327
    /** Listeners registered from MultiFileObject are considered as priority
1257
     *  listeners.
1328
     *  listeners.
1258
     */
1329
     */
(-)a/openide.filesystems/src/org/openide/filesystems/FileUtil.java (-58 / +35 lines)
Lines 58-68 Link Here
58
import java.net.URI;
58
import java.net.URI;
59
import java.net.URL;
59
import java.net.URL;
60
import java.net.URLStreamHandler;
60
import java.net.URLStreamHandler;
61
import java.nio.file.Files;
62
import java.nio.file.Path;
63
import java.security.AccessController;
64
import java.security.PrivilegedActionException;
65
import java.security.PrivilegedExceptionAction;
66
import java.util.ArrayList;
61
import java.util.ArrayList;
67
import java.util.Arrays;
62
import java.util.Arrays;
68
import java.util.Collection;
63
import java.util.Collection;
Lines 1446-1451 Link Here
1446
        return false;
1441
        return false;
1447
    }
1442
    }
1448
1443
1444
    /**
1445
     * Check whether some FileObject is a recursive symbolic link.
1446
     *
1447
     * @param fo FileObject to check.
1448
     *
1449
     * @return True if the FileObject represents a symbolic link referring to a
1450
     * directory that is parent of this FileObject, false otherwise.
1451
     * @throws java.io.IOException If some I/O problem occurs.
1452
     * @since openide.filesystem/9.4
1453
     */
1454
    public static boolean isRecursiveSymbolicLink(FileObject fo)
1455
            throws IOException {
1456
1457
        if (!fo.isFolder()) {
1458
            return false;
1459
        } else if (fo.isSymbolicLink()) {
1460
            FileObject parent = fo.getParent();
1461
            if (parent == null) {
1462
                return false;
1463
            }
1464
            FileObject target = fo.readSymbolicLink();
1465
            if (target != null) {
1466
                FileObject realParent = parent.getCanonicalFileObject();
1467
                FileObject realTarget = target.getCanonicalFileObject();
1468
                return realParent != null && realTarget != null
1469
                        && (realTarget.equals(realParent)
1470
                        || FileUtil.isParentOf(realTarget, realParent));
1471
            } else {
1472
                return false;
1473
            }
1474
        } else {
1475
            return false;
1476
        }
1477
    }
1478
1449
    /** Creates a weak implementation of FileChangeListener.
1479
    /** Creates a weak implementation of FileChangeListener.
1450
     *
1480
     *
1451
     * @param l the listener to delegate to
1481
     * @param l the listener to delegate to
Lines 2232-2288 Link Here
2232
        int index = path.lastIndexOf('.');  //NOI18N
2262
        int index = path.lastIndexOf('.');  //NOI18N
2233
        return (index != -1) && (index > path.lastIndexOf('/') + 1);    //NOI18N
2263
        return (index != -1) && (index > path.lastIndexOf('/') + 1);    //NOI18N
2234
    }
2264
    }
2235
2236
    /**
2237
     * Check whether this file is a symbolic link that targets to a folder
2238
     * higher in the path. Such link, in case of recursive folder traversing,
2239
     * would cause infinite recursion. The method should not be called from
2240
     * Event Dispatch Thread.
2241
     *
2242
     * @param fileObject FileObject to check.
2243
     * @return True if the file is a link that could cause infinite recursion,
2244
     * false otherwise.
2245
     */
2246
    static boolean isRecursiveSymlink(FileObject fileObject) {
2247
        File file = (File) fileObject.getAttribute("java.io.File"); // NOI18N
2248
        if (file == null) {
2249
            return false;
2250
        }
2251
        final Path path;
2252
        try {
2253
            path = file.toPath();
2254
        } catch (RuntimeException e) {
2255
            LOG.log(Level.INFO, "Cannot get path for {0}", file);       //NOI18N
2256
            LOG.log(Level.FINE, null, e);
2257
            return false;
2258
        }
2259
        if (Files.isSymbolicLink(path)) {
2260
            try {
2261
                return AccessController.doPrivileged(new PrivilegedExceptionAction<Boolean>() {
2262
                    @Override
2263
                    public Boolean run () throws IOException {
2264
                        Path target = Files.readSymbolicLink(path);
2265
                        if (!target.isAbsolute()) {
2266
                            target = path.resolve(target);
2267
                        }
2268
                        target = target.toRealPath();
2269
                        for (Path ancestor = path.getParent();
2270
                                ancestor != null; ancestor = ancestor.getParent()) {
2271
                            if (target.equals(ancestor)) {
2272
                                return true;
2273
                            }
2274
                        }
2275
                        return false;
2276
                    }
2277
                });
2278
            } catch (PrivilegedActionException ex) {
2279
                LOG.log(Level.INFO, "Cannot read symbolic link {0}",//NOI18N
2280
                        path);
2281
                LOG.log(Level.FINE, null, ex.getException());
2282
            } catch (SecurityException ex) {
2283
                LOG.log(Level.INFO, null, ex);
2284
            }
2285
        }
2286
        return false;
2287
    }
2288
}
2265
}
(-)a/openide.filesystems/src/org/openide/filesystems/LocalFileSystem.java (-3 / +32 lines)
Lines 57-65 Link Here
57
import java.io.ObjectInputValidation;
57
import java.io.ObjectInputValidation;
58
import java.io.OutputStream;
58
import java.io.OutputStream;
59
import java.io.SyncFailedException;
59
import java.io.SyncFailedException;
60
import java.nio.file.Files;
61
import java.nio.file.Path;
62
import java.nio.file.Paths;
60
import java.util.Random;
63
import java.util.Random;
61
import java.util.logging.Level;
64
import java.util.logging.Level;
62
import org.openide.util.Exceptions;
63
import org.openide.util.NbBundle;
65
import org.openide.util.NbBundle;
64
import org.openide.util.BaseUtilities;
66
import org.openide.util.BaseUtilities;
65
67
Lines 485-490 Link Here
485
    protected void markUnimportant(String name) {
487
    protected void markUnimportant(String name) {
486
    }
488
    }
487
489
490
    /**
491
     * Creates path for given string name.
492
     *
493
     * @param name File name.
494
     * @return The path.
495
     */
496
    private Path getPath(String name) {
497
        return Paths.get(rootFile.getPath(), name);
498
    }
499
488
    /** Creates file for given string name.
500
    /** Creates file for given string name.
489
    * @param name the name
501
    * @param name the name
490
    * @return the file
502
    * @return the file
Lines 519-526 Link Here
519
    * and Change interfaces and delegates all the methods
531
    * and Change interfaces and delegates all the methods
520
    * to appropriate methods of LocalFileSystem.
532
    * to appropriate methods of LocalFileSystem.
521
    */
533
    */
522
    public static class Impl extends Object implements AbstractFileSystem.List, AbstractFileSystem.Info,
534
    public static class Impl extends Object implements AbstractFileSystem.List,
523
        AbstractFileSystem.Change {
535
            AbstractFileSystem.Info, AbstractFileSystem.SymlinkInfo,
536
            AbstractFileSystem.Change {
537
524
        /** generated Serialized Version UID */
538
        /** generated Serialized Version UID */
525
        static final long serialVersionUID = -8432015909317698511L;
539
        static final long serialVersionUID = -8432015909317698511L;
526
540
Lines 690-695 Link Here
690
        public void markUnimportant(String name) {
704
        public void markUnimportant(String name) {
691
            fs.markUnimportant(name);
705
            fs.markUnimportant(name);
692
        }
706
        }
707
708
        @Override
709
        public boolean isSymbolicLink(String name) throws IOException {
710
            return Files.isSymbolicLink(fs.getPath(name));
711
        }
712
713
        @Override
714
        public String readSymbolicLink(String name) throws IOException {
715
            return Files.readSymbolicLink(fs.getPath(name)).toString();
716
        }
717
718
        @Override
719
        public String getCanonicalName(String name) throws IOException {
720
            return fs.getPath(name).toRealPath().toString();
721
        }
693
    }
722
    }
694
723
695
    /** This class adds new virtual attribute "java.io.File".
724
    /** This class adds new virtual attribute "java.io.File".

Return to bug 237882