1 /* 2 * Copyright (c) 2008, 2017, 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 /* 25 * @test 26 * @bug 7130915 27 * @summary Tests file path with nfc/nfd forms on MacOSX 28 * @requires (os.family == "mac") 29 * @library /java/nio/file 30 * @run main/othervm -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 MacPathTest 31 */ 32 33 import java.nio.file.DirectoryStream; 34 import java.nio.file.Files; 35 import java.nio.file.Path; 36 import java.nio.file.Paths; 37 import java.nio.file.attribute.PosixFilePermission; 38 import java.text.Normalizer; 39 import java.util.Locale; 40 import java.util.Set; 41 import java.util.regex.Pattern; 42 43 public class MacPathTest { 44 private static final String JNU_ENCODING = System.getProperty("sun.jnu.encoding"); 45 private static final String FILE_ENCODING = System.getProperty("file.encoding"); 46 47 public static void main(String args[]) throws Throwable { 48 if (!(FILE_ENCODING.equals("UTF-8") && JNU_ENCODING.equals("UTF-8"))) { 49 System.out.println("Warning: This test requires UTF-8, current encoding:" 50 + " sun.jnu.encoding = " + JNU_ENCODING + "," 51 + " file.encoding = " + FILE_ENCODING + "\n" 52 + "Test skipped.\n" 53 + "\nRun test with:\n" 54 + "java -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 MacPathTest"); 55 return; 56 } 57 58 Locale defaultLocale = Locale.getDefault(); 59 Locale.setDefault(Locale.US); 60 61 // English 62 test("TestDir_apple", // test dir 63 "dir_macosx", // dir 64 "file_macosx"); // file 65 66 // Japanese composite character 67 test("TestDir_\u30c8\u30a4\u30e4\u30cb\u30ca\u30eb/", 68 "dir_\u30a4\u30c1\u30b4\u306e\u30b1\u30fc\u30ad", 69 "file_\u30a4\u30c1\u30b4\u306e\u30b1\u30fc\u30ad"); 70 71 // latin-1 supplementory 72 test("TestDir_K\u00f6rperlich\u00e4\u00df/", 73 "dir_Entt\u00e4uschung", 74 "file_Entt\u00e4uschung"); 75 76 test("TestDir_K\u00f6rperlich\u00e4\u00df/", 77 "dir_Entt\u00c4uschung", 78 "file_Entt\u00c4uschung"); 79 80 // Korean syblla 81 test("TestDir_\uac00\uac01\uac02", 82 "dir_\uac20\uac21\uac22", 83 "file_\uacc0\uacc1\uacc2"); 84 85 Locale.setDefault(defaultLocale); //restore 86 } 87 88 private static boolean equal(Object x, Object y) { 89 return x == null ? y == null : x.equals(y); 90 } 91 92 private static boolean match(Path target, Path src) { 93 String fname = target.toString(); 94 System.out.printf(" --> Trying [%s], length=%d...", fname, fname.length()); 95 if (target.equals(src)) { 96 System.out.println(" MATCHED!"); 97 return true; 98 } else { 99 System.out.println(" NOT MATCHED!"); 100 } 101 return false; 102 } 103 104 private static void test(String testdir, String dname, String fname_nfc) 105 throws Throwable 106 { 107 String fname = null; 108 String dname_nfd = Normalizer.normalize(dname, Normalizer.Form.NFD); 109 String fname_nfd = Normalizer.normalize(fname_nfc, Normalizer.Form.NFD); 110 111 System.out.printf("%n%n--------Testing...----------%n"); 112 Path bpath = Paths.get(testdir); 113 Path dpath = Paths.get(testdir, dname); 114 Path dpath_nfd = Paths.get(testdir, dname_nfd); 115 Path fpath_nfc = Paths.get(testdir, fname_nfc); 116 Path fpath_nfd = Paths.get(testdir, fname_nfd); 117 118 if (Files.exists(bpath)) 119 TestUtil.removeAll(bpath); 120 Files.createDirectories(dpath); 121 122 fname = dpath.toString(); 123 System.out.printf(":Directory [%s][len=%d] created%n", fname, fname.length()); 124 125 ////////////////////////////////////////////////////////////// 126 if (!Files.isDirectory(dpath) || !Files.isDirectory(dpath_nfd)) { 127 throw new RuntimeException("Files.isDirectory(...) failed"); 128 } 129 130 ////////////////////////////////////////////////////////////// 131 // write out with nfd, read in with nfc + case 132 Files.write(fpath_nfd, new byte[] { 'n', 'f', 'd'}); 133 System.out.println(" read in with nfc (from nfd):" + new String(Files.readAllBytes(fpath_nfc))); 134 135 // check attrs with nfc + case 136 Set<PosixFilePermission> pfp = Files.getPosixFilePermissions(fpath_nfd); 137 if (!equal(pfp, Files.getPosixFilePermissions(fpath_nfc)) ) { 138 throw new RuntimeException("Files.getPosixfilePermission(...) failed"); 139 } 140 Files.delete(fpath_nfd); 141 142 // write out with nfc, read in with nfd + case 143 Files.write(fpath_nfc, new byte[] { 'n', 'f', 'c'}); 144 System.out.println(" read in with nfd (from nfc):" + new String(Files.readAllBytes(fpath_nfd))); 145 146 // check attrs with nfc + case 147 pfp = Files.getPosixFilePermissions(fpath_nfc); 148 if (!equal(pfp, Files.getPosixFilePermissions(fpath_nfd))) { 149 throw new RuntimeException("Files.getPosixfilePermission(...) failed"); 150 } 151 ////////////////////////////////////////////////////////////// 152 boolean found_dir = false; 153 boolean found_file_nfc = false; 154 boolean found_file_nfd = false; 155 try (DirectoryStream<Path> stream = Files.newDirectoryStream(bpath)) { 156 for (Path path: stream) { 157 fname = path.toString(); 158 System.out.printf("Found : [%s], length=%d%n", fname, fname.length()); 159 found_dir |= match(dpath, path); 160 found_file_nfc |= match(fpath_nfc, path); 161 found_file_nfd |= match(fpath_nfd, path); 162 } 163 } 164 if (!found_dir || !found_file_nfc || !found_file_nfd) { 165 throw new RuntimeException("File.equal() failed"); 166 } 167 // glob 168 String glob = "*" + fname_nfd.substring(2); // remove leading "FI" from "FILE..." 169 System.out.println("glob=" + glob); 170 boolean globmatched = false; 171 try (DirectoryStream<Path> stream = Files.newDirectoryStream(bpath, glob)) { 172 for (Path path: stream) { 173 fname = path.toString(); 174 System.out.printf("PathMatch : [%s], length=%d%n", fname, fname.length()); 175 globmatched |= match(fpath_nfc, path); 176 } 177 } 178 if (!globmatched) { 179 //throw new RuntimeException("path matcher failed"); 180 // it appears we have a regex.anon_eq bug in hangul syllable handling 181 System.out.printf("pathmatcher failed, glob=[%s]%n", glob); 182 System.out.printf(" -> fname_nfd.matches(fname_nfc)=%b%n", 183 Pattern.compile(fname_nfd, Pattern.CANON_EQ) 184 .matcher(fname_nfc) 185 .matches()); 186 System.out.printf(" -> fname_nfc.matches(fname_nfd)=%b%n", 187 Pattern.compile(fname_nfc, Pattern.CANON_EQ) 188 .matcher(fname_nfd) 189 .matches()); 190 } 191 TestUtil.removeAll(bpath); 192 } 193 }