1/*
2 * Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.
8 *
9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12 * version 2 for more details (a copy is included in the LICENSE file that
13 * accompanied this code).
14 *
15 * You should have received a copy of the GNU General Public License version
16 * 2 along with this work; if not, write to the Free Software Foundation,
17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 *
19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 * or visit www.oracle.com if you need additional information or have any
21 * questions.
22 */
23
24/* @test
25 * @bug 4313887 6838333 6863864
26 * @summary Unit test for java.nio.file.Files createSymbolicLink,
27 *     readSymbolicLink, and createLink methods
28 * @library ..
29 * @build Links
30 * @run main/othervm Links
31 */
32
33import java.nio.file.*;
34import java.nio.file.attribute.*;
35import java.io.*;
36
37public class Links {
38
39    static final boolean isWindows =
40        System.getProperty("os.name").startsWith("Windows");
41
42    static void assertTrue(boolean okay) {
43        if (!okay)
44            throw new RuntimeException("Assertion failed");
45    }
46
47    /**
48     * Exercise createSymbolicLink and readLink methods
49     */
50    static void testSymLinks(Path dir) throws IOException {
51        final Path link = dir.resolve("link");
52
53        // Check if sym links are supported
54        try {
55            Files.createSymbolicLink(link, Paths.get("foo"));
56            Files.delete(link);
57        } catch (UnsupportedOperationException x) {
58            // sym links not supported
59            return;
60        } catch (IOException x) {
61            // probably insufficient privileges to create sym links (Windows)
62            return;
63        }
64
65        // Test links to various targets
66        String[] windowsTargets =
67            { "foo", "C:\\foo", "\\foo", "\\\\server\\share\\foo" };
68        String[] otherTargets = { "relative", "/absolute" };
69
70        String[] targets = (isWindows) ? windowsTargets : otherTargets;
71        for (String s: targets) {
72            Path target = Paths.get(s);
73            Files.createSymbolicLink(link, target);
74            try {
75                assertTrue(Files.readSymbolicLink(link).equals(target));
76            } finally {
77                Files.delete(link);
78            }
79        }
80
81        // Test links to directory
82        Path mydir = dir.resolve("mydir");
83        Path myfile = mydir.resolve("myfile");
84        try {
85            Files.createDirectory(mydir);
86            Files.createFile(myfile);
87
88            // link -> "mydir"
89            Files.createSymbolicLink(link, mydir.getFileName());
90            assertTrue(Files.readSymbolicLink(link).equals(mydir.getFileName()));
91
92            // Test access to directory via link
93            try (DirectoryStream<Path> stream = Files.newDirectoryStream(link)) {
94                boolean found = false;
95                for (Path entry: stream) {
96                    if (entry.getFileName().equals(myfile.getFileName())) {
97                        found = true;
98                        break;
99                    }
100                }
101                assertTrue(found);
102            }
103
104            // Test link2 -> link -> mydir
105            final Path link2 = dir.resolve("link2");
106            Path target2 = link.getFileName();
107            Files.createSymbolicLink(link2, target2);
108            try {
109                assertTrue(Files.readSymbolicLink(link2).equals(target2));
110                Files.newDirectoryStream(link2).close();
111            } finally {
112                Files.delete(link2);
113            }
114
115            // Remove mydir and re-create link2 before re-creating mydir
116            // (This is a useful test on Windows to ensure that creating a
117            // sym link to a directory sym link creates the right type of link).
118            Files.delete(myfile);
119            Files.delete(mydir);
120            Files.createSymbolicLink(link2, target2);
121            try {
122                assertTrue(Files.readSymbolicLink(link2).equals(target2));
123                Files.createDirectory(mydir);
124                Files.newDirectoryStream(link2).close();
125            } finally {
126                Files.delete(link2);
127            }
128
129        } finally {
130            Files.deleteIfExists(myfile);
131            Files.deleteIfExists(mydir);
132            Files.deleteIfExists(link);
133        }
134    }
135
136    /**
137     * Exercise createLink method
138     */
139    static void testHardLinks(Path dir) throws IOException {
140        Path foo = dir.resolve("foo");
141        Files.createFile(foo);
142        try {
143            Path bar = dir.resolve("bar");
144            try {
145                Files.createLink(bar, foo);
146            } catch (UnsupportedOperationException x) {
147                return;
148            } catch (IOException x) {
149                // probably insufficient privileges (Windows)
150                return;
151            }
152            try {
153                Object key1 = Files.readAttributes(foo, BasicFileAttributes.class).fileKey();
154                Object key2 = Files.readAttributes(bar, BasicFileAttributes.class).fileKey();
155                assertTrue((key1 == null) || (key1.equals(key2)));
156            } finally {
157                Files.delete(bar);
158            }
159
160
161        } finally {
162            Files.delete(foo);
163        }
164    }
165
166    public static void main(String[] args) throws IOException {
167        Path dir = TestUtil.createTemporaryDirectory();
168        try {
169            testSymLinks(dir);
170            testHardLinks(dir);
171
172            // repeat tests on Windows with long path
173            if (isWindows) {
174                Path dirWithLongPath = null;
175                try {
176                    dirWithLongPath = TestUtil.createDirectoryWithLongPath(dir);
177                } catch (IOException x) {
178                    System.out.println("Unable to create long path: " + x);
179                }
180                if (dirWithLongPath != null) {
181                    System.out.println("");
182                    System.out.println("** REPEAT TESTS WITH LONG PATH **");
183                    testSymLinks(dirWithLongPath);
184                    testHardLinks(dirWithLongPath);
185                }
186            }
187        } finally {
188            TestUtil.removeAll(dir);
189        }
190    }
191}
192