提交 9e61768c 编写于 作者: S sherman

7130915: File.equals does not give expected results when path contains...

7130915: File.equals does not give expected results when path contains Non-English characters on Mac OS X
Summary: to support Unicode nfd/nfc file path on Macos
Reviewed-by: alanb
上级 2eea56c3
......@@ -282,6 +282,9 @@ FILES_java += \
sun/nio/fs/BsdFileSystem.java \
sun/nio/fs/BsdFileSystemProvider.java \
sun/nio/fs/BsdNativeDispatcher.java \
sun/nio/fs/MacOSXFileSystemProvider.java \
sun/nio/fs/MacOSXFileSystem.java \
sun/nio/fs/MacOSXNativeDispatcher.java \
sun/nio/fs/PollingWatchService.java \
sun/nio/fs/UnixChannelFactory.java \
sun/nio/fs/UnixCopyFile.java \
......@@ -311,6 +314,7 @@ FILES_c += \
\
GnomeFileTypeDetector.c \
BsdNativeDispatcher.c \
MacOSXNativeDispatcher.c \
UnixCopyFile.c \
UnixNativeDispatcher.c \
\
......@@ -385,7 +389,7 @@ ifeq ($(PLATFORM), linux)
OTHER_LDLIBS += -L$(LIBDIR)/$(LIBARCH) -ljava -lnet -lpthread $(LIBDL)
endif
ifeq ($(PLATFORM), macosx)
OTHER_LDLIBS += -L$(LIBDIR) -ljava -lnet -pthread
OTHER_LDLIBS += -L$(LIBDIR) -ljava -lnet -pthread -framework CoreFoundation
endif
ifeq ($(PLATFORM), solaris)
OTHER_LDLIBS += $(JVMLIB) $(LIBSOCKET) -lposix4 $(LIBDL) -lsendfile \
......
......@@ -25,9 +25,6 @@
#include "jni.h"
#include "jni_util.h"
#ifdef MACOSX
char* convertToNFDIfNeeded(const char *origPath, char *buf, size_t bufsize);
#endif
extern jfieldID IO_fd_fdID;
extern jfieldID IO_handle_fdID;
......@@ -59,7 +56,6 @@ void fileOpen(JNIEnv *env, jobject this, jstring path, jfieldID fid, int flags);
void throwFileNotFoundException(JNIEnv *env, jstring path);
/*
* Macros for managing platform strings. The typical usage pattern is:
*
......@@ -88,35 +84,6 @@ void throwFileNotFoundException(JNIEnv *env, jstring path);
* declares a unique variable.
*/
#ifdef MACOSX
#define WITH_PLATFORM_STRING(env, strexp, var) \
if (1) { \
const char *var; \
jstring _##var##str = (strexp); \
if (_##var##str == NULL) { \
JNU_ThrowNullPointerException((env), NULL); \
goto _##var##end; \
} \
const char *temp_var = JNU_GetStringPlatformChars((env), _##var##str, NULL); \
if (temp_var == NULL) goto _##var##end; \
char buf[MAXPATHLEN]; \
var = convertToNFDIfNeeded(temp_var, buf, sizeof(buf));
#define WITH_FIELD_PLATFORM_STRING(env, object, id, var) \
WITH_PLATFORM_STRING(env, \
((object == NULL) \
? NULL \
: (*(env))->GetObjectField((env), (object), (id))), \
var)
#define END_PLATFORM_STRING(env, var) \
JNU_ReleaseStringPlatformChars(env, _##var##str, temp_var); \
_##var##end: ; \
} else ((void)NULL)
#else
#define WITH_PLATFORM_STRING(env, strexp, var) \
if (1) { \
const char *var; \
......@@ -140,8 +107,6 @@ void throwFileNotFoundException(JNIEnv *env, jstring path);
_##var##end: ; \
} else ((void)NULL)
#endif
/* Macros for transforming Java Strings into native Unicode strings.
* Works analogously to WITH_PLATFORM_STRING.
......
......@@ -33,7 +33,7 @@ import java.security.PrivilegedAction;
*/
class BsdNativeDispatcher extends UnixNativeDispatcher {
private BsdNativeDispatcher() { }
protected BsdNativeDispatcher() { }
/**
* struct fsstat_iter *getfsstat();
......@@ -55,11 +55,6 @@ class BsdNativeDispatcher extends UnixNativeDispatcher {
private static native void initIDs();
static {
AccessController.doPrivileged(new PrivilegedAction<Void>() {
public Void run() {
System.loadLibrary("nio");
return null;
}});
initIDs();
initIDs();
}
}
......@@ -69,7 +69,7 @@ public class DefaultFileSystemProvider {
if (osname.equals("Linux"))
return createProvider("sun.nio.fs.LinuxFileSystemProvider");
if (osname.equals("Darwin") || osname.contains("OS X"))
return createProvider("sun.nio.fs.BsdFileSystemProvider");
return createProvider("sun.nio.fs.MacOSXFileSystemProvider");
throw new AssertionError("Platform not recognized");
}
}
/*
* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.nio.fs;
import java.nio.file.*;
import java.io.IOException;
import java.util.*;
import java.util.regex.Pattern;
import java.security.AccessController;
import sun.security.action.GetPropertyAction;
import static sun.nio.fs.MacOSXNativeDispatcher.*;
/**
* MacOS implementation of FileSystem
*/
class MacOSXFileSystem extends BsdFileSystem {
MacOSXFileSystem(UnixFileSystemProvider provider, String dir) {
super(provider, dir);
}
// match in unicode canon_eq
Pattern compilePathMatchPattern(String expr) {
return Pattern.compile(expr, Pattern.CANON_EQ) ;
}
char[] normalizeNativePath(char[] path) {
for (char c : path) {
if (c > 0x80)
return normalizepath(path, kCFStringNormalizationFormD);
}
return path;
}
String normalizeJavaPath(String path) {
for (int i = 0; i < path.length(); i++) {
if (path.charAt(i) > 0x80)
return new String(normalizepath(path.toCharArray(),
kCFStringNormalizationFormC));
}
return path;
}
}
/*
* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.nio.fs;
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.io.IOException;
/**
* MacOSX implementation of FileSystemProvider
*/
public class MacOSXFileSystemProvider extends BsdFileSystemProvider {
public MacOSXFileSystemProvider() {
super();
}
@Override
MacOSXFileSystem newFileSystem(String dir) {
return new MacOSXFileSystem(this, dir);
}
}
/*
* Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package sun.nio.fs;
import java.security.AccessController;
import java.security.PrivilegedAction;
/**
* MacOSX specific system calls.
*/
class MacOSXNativeDispatcher extends BsdNativeDispatcher {
private MacOSXNativeDispatcher() { }
static final int kCFStringNormalizationFormC = 2;
static final int kCFStringNormalizationFormD = 0;
static native char[] normalizepath(char[] path, int form);
}
......@@ -302,7 +302,8 @@ abstract class UnixFileSystem
}
// return matcher
final Pattern pattern = Pattern.compile(expr);
final Pattern pattern = compilePathMatchPattern(expr);
return new PathMatcher() {
@Override
public boolean matches(Path path) {
......@@ -310,11 +311,10 @@ abstract class UnixFileSystem
}
};
}
private static final String GLOB_SYNTAX = "glob";
private static final String REGEX_SYNTAX = "regex";
@Override
public final UserPrincipalLookupService getUserPrincipalLookupService() {
return LookupService.instance;
......@@ -339,4 +339,23 @@ abstract class UnixFileSystem
};
}
// Override if the platform has different path match requrement, such as
// case insensitive or Unicode canonical equal on MacOSX
Pattern compilePathMatchPattern(String expr) {
return Pattern.compile(expr);
}
// Override if the platform uses different Unicode normalization form
// for native file path. For example on MacOSX, the native path is stored
// in Unicode NFD form.
char[] normalizeNativePath(char[] path) {
return path;
}
// Override if the native file path use non-NFC form. For example on MacOSX,
// the native path is stored in Unicode NFD form, the path need to be
// normalized back to NFC before passed back to Java level.
String normalizeJavaPath(String path) {
return path;
}
}
......@@ -68,7 +68,7 @@ class UnixPath
UnixPath(UnixFileSystem fs, String input) {
// removes redundant slashes and checks for invalid characters
this(fs, encode(normalizeAndCheck(input)));
this(fs, encode(fs, normalizeAndCheck(input)));
}
// package-private
......@@ -116,7 +116,7 @@ class UnixPath
}
// encodes the given path-string into a sequence of bytes
private static byte[] encode(String input) {
private static byte[] encode(UnixFileSystem fs, String input) {
SoftReference<CharsetEncoder> ref = encoder.get();
CharsetEncoder ce = (ref != null) ? ref.get() : null;
if (ce == null) {
......@@ -126,7 +126,7 @@ class UnixPath
encoder.set(new SoftReference<CharsetEncoder>(ce));
}
char[] ca = input.toCharArray();
char[] ca = fs.normalizeNativePath(input.toCharArray());
// size output buffer for worse-case size
byte[] ba = new byte[(int)(ca.length * (double)ce.maxBytesPerChar())];
......@@ -728,7 +728,7 @@ class UnixPath
if (c1 != c2) {
return c1 - c2;
}
k++;
k++;
}
return len1 - len2;
}
......@@ -757,8 +757,9 @@ class UnixPath
@Override
public String toString() {
// OK if two or more threads create a String
if (stringValue == null)
stringValue = new String(path); // platform encoding
if (stringValue == null) {
stringValue = fs.normalizeJavaPath(new String(path)); // platform encoding
}
return stringValue;
}
......
......@@ -38,6 +38,7 @@
#include "jlong.h"
#include "jvm.h"
#include "io_util.h"
#include "io_util_md.h"
#include "java_io_FileSystem.h"
#include "java_io_UnixFileSystem.h"
......@@ -80,7 +81,11 @@ Java_java_io_UnixFileSystem_canonicalize0(JNIEnv *env, jobject this,
canonicalPath, JVM_MAXPATHLEN) < 0) {
JNU_ThrowIOExceptionWithLastError(env, "Bad pathname");
} else {
#ifdef MACOSX
rv = newStringPlatform(env, canonicalPath);
#else
rv = JNU_NewStringPlatform(env, canonicalPath);
#endif
}
} END_PLATFORM_STRING(env, path);
return rv;
......@@ -311,7 +316,11 @@ Java_java_io_UnixFileSystem_list(JNIEnv *env, jobject this,
if (JNU_CopyObjectArray(env, rv, old, len) < 0) goto error;
(*env)->DeleteLocalRef(env, old);
}
#ifdef MACOSX
name = newStringPlatform(env, ptr->d_name);
#else
name = JNU_NewStringPlatform(env, ptr->d_name);
#endif
if (name == NULL) goto error;
(*env)->SetObjectArrayElement(env, rv, len++, name);
(*env)->DeleteLocalRef(env, name);
......
......@@ -34,37 +34,32 @@
#include <CoreFoundation/CoreFoundation.h>
static inline char *convertToNFD(const char *path, char *buf, size_t bufsize)
{
CFMutableStringRef mutable = CFStringCreateMutable(NULL, 0);
CFStringAppendCString(mutable, path, kCFStringEncodingUTF8);
CFStringNormalize(mutable, kCFStringNormalizationFormD);
CFStringGetCString(mutable, buf, bufsize, kCFStringEncodingUTF8);
CFRelease(mutable);
return buf;
}
/* Converts the path to NFD form if it was in NFC form. Returns a pointer to
* the converting string which could be buf (if the converstion took place) or
* origPath if no conversion was needed
*/
__private_extern__
char* convertToNFDIfNeeded(const char *origPath, char *buf, size_t bufsize)
jstring newStringPlatform(JNIEnv *env, const char* str)
{
const char *current = origPath;
int c;
for (c = *current; c != 0; current++, c = *current) {
if (c < 0) {
// Need to convert
return convertToNFD(origPath, buf, bufsize);
jstring rv = NULL;
CFMutableStringRef csref = CFStringCreateMutable(NULL, 0);
if (csref == NULL) {
JNU_ThrowOutOfMemoryError(env, "native heap");
} else {
CFStringAppendCString(csref, str, kCFStringEncodingUTF8);
CFStringNormalize(csref, kCFStringNormalizationFormC);
int clen = CFStringGetLength(csref);
int ulen = (clen + 1) * 2; // utf16 + zero padding
char* chars = malloc(ulen);
if (chars == NULL) {
CFRelease(csref);
JNU_ThrowOutOfMemoryError(env, "native heap");
} else {
if (CFStringGetCString(csref, chars, ulen, kCFStringEncodingUTF16)) {
rv = (*env)->NewString(env, (jchar*)chars, clen);
}
free(chars);
CFRelease(csref);
}
}
return (char *)origPath;
return rv;
}
#endif
void
......
......@@ -72,3 +72,7 @@
* IO helper function(s)
*/
void fileClose(JNIEnv *env, jobject this, jfieldID fid);
#ifdef MACOSX
jstring newStringPlatform(JNIEnv *env, const char* str);
#endif
/*
* Copyright (c) 2008, 2009, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include "jni.h"
#include "jni_util.h"
#include "jvm.h"
#include "jlong.h"
#include <stdlib.h>
#include <string.h>
#include <CoreFoundation/CoreFoundation.h>
JNIEXPORT jcharArray JNICALL
Java_sun_nio_fs_MacOSXNativeDispatcher_normalizepath(JNIEnv* env, jclass this,
jcharArray path,
jint form)
{
jcharArray result = NULL;
char chars_buf[(PATH_MAX + 1) * 2]; // utf16 + zero padding
CFMutableStringRef csref = CFStringCreateMutable(NULL, 0);
if (csref == NULL) {
JNU_ThrowOutOfMemoryError(env, "native heap");
} else {
char *chars = (char*)(*env)->GetPrimitiveArrayCritical(env, path, 0);
jsize len = (*env)->GetArrayLength(env, path);
CFStringAppendCharacters(csref, (const UniChar*)chars, len);
(*env)->ReleasePrimitiveArrayCritical(env, path, chars, 0);
CFStringNormalize(csref, form);
len = CFStringGetLength(csref);
if (len < PATH_MAX) {
if (CFStringGetCString(csref, chars_buf, sizeof(chars_buf), kCFStringEncodingUTF16)) {
result = (*env)->NewCharArray(env, len);
(*env)->SetCharArrayRegion(env, result, 0, len, (jchar*)&chars_buf);
}
} else {
int ulen = (len + 1) * 2;
chars = malloc(ulen);
if (chars == NULL) {
CFRelease(csref);
JNU_ThrowOutOfMemoryError(env, "native heap");
return result;
} else {
if (CFStringGetCString(csref, chars, ulen, kCFStringEncodingUTF16)) {
result = (*env)->NewCharArray(env, len);
(*env)->SetCharArrayRegion(env, result, 0, len, (jchar*)chars);
}
free(chars);
}
}
CFRelease(csref);
}
return result;
}
/*
* Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* @test
* @bug 7130915
* @summary Tests file path with nfc/nfd forms on MacOSX
* @build MacPathTest
* @run shell MacPathTest.sh
*/
import java.io.*;
import java.text.*;
import java.util.*;
public class MacPathTest {
public static void main(String args[]) throws Throwable {
String osname = System.getProperty("os.name");
if (!osname.contains("OS X") && !osname.contains("Darwin"))
return;
// English
test("TestDir_apple", // test dir
"dir_macosx", // dir
"file_macosx"); // file
// Japanese composite character
test("TestDir_\u30c8\u30a4\u30e4\u30cb\u30ca\u30eb/",
"dir_\u30a4\u30c1\u30b4\u306e\u30b1\u30fc\u30ad",
"file_\u30a4\u30c1\u30b4\u306e\u30b1\u30fc\u30ad");
// latin-1 supplementory
test("TestDir_K\u00f6rperlich\u00e4\u00df/",
"dir_Entt\u00e4uschung",
"file_Entt\u00e4uschung");
test("TestDir_K\u00f6rperlich\u00e4\u00df/",
"dir_Entt\u00c4uschung",
"file_Entt\u00c4uschung");
// Korean syblla
test("TestDir_\uac00\uac01\uac02",
"dir_\uac20\uac21\uac22",
"file_\uacc0\uacc1\uacc2");
}
private static void removeAll(File file) throws Throwable {
if (file.isDirectory()) {
for (File f : file.listFiles()) {
removeAll(f);
}
}
file.delete();
}
private static boolean equal(Object x, Object y) {
return x == null ? y == null : x.equals(y);
}
private static boolean match(File target, File src) {
if (target.equals(src)) {
String fname = target.toString();
System.out.printf(" ->matched : [%s], length=%d%n", fname, fname.length());
return true;
}
return false;
}
private static void open_read(String what, File file) throws Throwable {
try (FileInputStream fis = new FileInputStream(file)) {
byte[] bytes = new byte[10];
fis.read(bytes);
System.out.printf(" %s:%s%n", what, new String(bytes));
}
}
private static void test(String testdir, String dname, String fname_nfc)
throws Throwable
{
String fname = null;
String dname_nfd = Normalizer.normalize(dname, Normalizer.Form.NFD);
String fname_nfd = Normalizer.normalize(fname_nfc, Normalizer.Form.NFD);
System.out.printf("%n%n--------Testing...----------%n");
File base = new File(testdir);
File dir = new File(base, dname);
File dir_nfd = new File(base, dname_nfd);
File file_nfc = new File(base, fname_nfc);
File file_nfd = new File(base, fname_nfd);
System.out.printf("base :[%s][len=%d]%n", testdir, testdir.length());
System.out.printf("dir :[%s][len=%d]%n", dname, dname.length());
System.out.printf("fname_nfc :[%s][len=%d]%n", fname_nfc, fname_nfc.length());
System.out.printf("fname_nfd :[%s][len=%d]%n", fname_nfd, fname_nfd.length());
fname = file_nfc.toString();
System.out.printf("file_nfc ->[%s][len=%d]%n", fname, fname.length());
fname = file_nfd.toString();
System.out.printf("file_nfd ->[%s][len=%d]%n%n", fname, fname.length());
removeAll(base);
dir.mkdirs();
fname = dir.toString();
System.out.printf(":Directory [%s][len=%d] created%n", fname, fname.length());
//////////////////////////////////////////////////////////////
if (!dir.isDirectory() || !dir_nfd.isDirectory()) {
throw new RuntimeException("File.isDirectory() failed");
}
//////////////////////////////////////////////////////////////
// write to via nfd
try (FileOutputStream fos = new FileOutputStream(file_nfd)) {
fos.write('n'); fos.write('f'); fos.write('d');
}
open_read("read in with nfc (from nfd)", file_nfc);
file_nfd.delete();
//////////////////////////////////////////////////////////////
// write to with nfc
try (FileOutputStream fos = new FileOutputStream(file_nfc)) {
fos.write('n'); fos.write('f'); fos.write('c');
}
open_read("read in with nfd (from nfc)", file_nfd);
//file_nfc.delete();
//////////////////////////////////////////////////////////////
boolean found_dir = false;
boolean found_file_nfc = false;
boolean found_file_nfd = false;
for (File f : base.listFiles()) {
fname = f.toString();
System.out.printf("Found : [%s], length=%d%n", fname, fname.length());
found_dir |= match(dir, f);
found_file_nfc |= match(file_nfc, f);
found_file_nfd |= match(file_nfd, f);
}
if (!found_dir || !found_file_nfc || !found_file_nfc) {
throw new RuntimeException("File.equal() failed");
}
removeAll(base);
}
}
#! /bin/sh
#
# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
#
OS=`uname -s`
case "$OS" in
Darwin ) ;;
* )
exit 0
;;
esac
if [ "x$TESTJAVA" = x ]; then
TESTJAVA=$1; shift
TESTCLASSES=.
fi
export LC_ALL=en_US.UTF-8 ;${TESTJAVA}/bin/java -cp ${TESTCLASSES} MacPathTest
/*
* Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
/* @test
* @bug 7130915
* @summary Tests file path with nfc/nfd forms on MacOSX
* @library ../
* @build MacPathTest
* @run shell MacPathTest.sh
*/
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.text.*;
import java.util.*;
import java.util.regex.*;
public class MacPathTest {
public static void main(String args[]) throws Throwable {
String osname = System.getProperty("os.name");
if (!osname.contains("OS X") && !osname.contains("Darwin"))
return;
System.out.printf("sun.jnu.encoding=%s, file.encoding=%s%n",
System.getProperty("file.encoding"),
System.getProperty("sun.jnu.encoding"));
// English
test("TestDir_apple", // test dir
"dir_macosx", // dir
"file_macosx"); // file
// Japanese composite character
test("TestDir_\u30c8\u30a4\u30e4\u30cb\u30ca\u30eb/",
"dir_\u30a4\u30c1\u30b4\u306e\u30b1\u30fc\u30ad",
"file_\u30a4\u30c1\u30b4\u306e\u30b1\u30fc\u30ad");
// latin-1 supplementory
test("TestDir_K\u00f6rperlich\u00e4\u00df/",
"dir_Entt\u00e4uschung",
"file_Entt\u00e4uschung");
test("TestDir_K\u00f6rperlich\u00e4\u00df/",
"dir_Entt\u00c4uschung",
"file_Entt\u00c4uschung");
// Korean syblla
test("TestDir_\uac00\uac01\uac02",
"dir_\uac20\uac21\uac22",
"file_\uacc0\uacc1\uacc2");
}
private static boolean equal(Object x, Object y) {
return x == null ? y == null : x.equals(y);
}
private static boolean match(Path target, Path src) {
String fname = target.toString();
System.out.printf(" --> Trying [%s], length=%d...", fname, fname.length());
if (target.equals(src)) {
System.out.println(" MATCHED!");
return true;
} else {
System.out.println(" NOT MATCHED!");
}
return false;
}
private static void test(String testdir, String dname, String fname_nfc)
throws Throwable
{
String fname = null;
String dname_nfd = Normalizer.normalize(dname, Normalizer.Form.NFD);
String fname_nfd = Normalizer.normalize(fname_nfc, Normalizer.Form.NFD);
System.out.printf("%n%n--------Testing...----------%n");
Path bpath = Paths.get(testdir);
Path dpath = Paths.get(testdir, dname);
Path dpath_nfd = Paths.get(testdir, dname_nfd);
Path fpath_nfc = Paths.get(testdir, fname_nfc);
Path fpath_nfd = Paths.get(testdir, fname_nfd);
if (Files.exists(bpath))
TestUtil.removeAll(bpath);
Files.createDirectories(dpath);
fname = dpath.toString();
System.out.printf(":Directory [%s][len=%d] created%n", fname, fname.length());
//////////////////////////////////////////////////////////////
if (!Files.isDirectory(dpath) || !Files.isDirectory(dpath_nfd)) {
throw new RuntimeException("Files.isDirectory(...) failed");
}
//////////////////////////////////////////////////////////////
// write out with nfd, read in with nfc + case
Files.write(fpath_nfd, new byte[] { 'n', 'f', 'd'});
System.out.println(" read in with nfc (from nfd):" + new String(Files.readAllBytes(fpath_nfc)));
// check attrs with nfc + case
Set<PosixFilePermission> pfp = Files.getPosixFilePermissions(fpath_nfd);
if (!equal(pfp, Files.getPosixFilePermissions(fpath_nfc)) ) {
throw new RuntimeException("Files.getPosixfilePermission(...) failed");
}
Files.delete(fpath_nfd);
// write out with nfc, read in with nfd + case
Files.write(fpath_nfc, new byte[] { 'n', 'f', 'c'});
System.out.println(" read in with nfd (from nfc):" + new String(Files.readAllBytes(fpath_nfd)));
// check attrs with nfc + case
pfp = Files.getPosixFilePermissions(fpath_nfc);
if (!equal(pfp, Files.getPosixFilePermissions(fpath_nfd))) {
throw new RuntimeException("Files.getPosixfilePermission(...) failed");
}
//////////////////////////////////////////////////////////////
boolean found_dir = false;
boolean found_file_nfc = false;
boolean found_file_nfd = false;
try (DirectoryStream<Path> stream = Files.newDirectoryStream(bpath)) {
for (Path path: stream) {
fname = path.toString();
System.out.printf("Found : [%s], length=%d%n", fname, fname.length());
found_dir |= match(dpath, path);
found_file_nfc |= match(fpath_nfc, path);
found_file_nfd |= match(fpath_nfd, path);
}
}
if (!found_dir || !found_file_nfc || !found_file_nfd) {
throw new RuntimeException("File.equal() failed");
}
// glob
String glob = "*" + fname_nfd.substring(2); // remove leading "FI" from "FILE..."
System.out.println("glob=" + glob);
boolean globmatched = false;
try (DirectoryStream<Path> stream = Files.newDirectoryStream(bpath, glob)) {
for (Path path: stream) {
fname = path.toString();
System.out.printf("PathMatch : [%s], length=%d%n", fname, fname.length());
globmatched |= match(fpath_nfc, path);
}
}
if (!globmatched) {
//throw new RuntimeException("path matcher failed");
// it appears we have a regex.anon_eq bug in hangul syllable handling
System.out.printf("pathmatcher failed, glob=[%s]%n", glob);
System.out.printf(" -> fname_nfd.matches(fname_nfc)=%b%n",
Pattern.compile(fname_nfd, Pattern.CANON_EQ)
.matcher(fname_nfc)
.matches());
System.out.printf(" -> fname_nfc.matches(fname_nfd)=%b%n",
Pattern.compile(fname_nfc, Pattern.CANON_EQ)
.matcher(fname_nfd)
.matches());
}
TestUtil.removeAll(bpath);
}
}
#! /bin/sh
#
# Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
#
# This code is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#
#
OS=`uname -s`
case "$OS" in
Darwin ) ;;
* )
exit 0
;;
esac
if [ "x$TESTJAVA" = x ]; then
TESTJAVA=$1; shift
TESTCLASSES=.
fi
export LC_ALL=en_US.UTF-8; ${TESTJAVA}/bin/java -cp ${TESTCLASSES} MacPathTest
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册