mirror of
https://github.com/openjdk/jdk.git
synced 2026-02-03 06:58:23 +00:00
8129632: (fs) Files.probeContentType returns null on Mac OS X
Append a Uniform Type Identifier-based FileType Detector for Mac OS X Reviewed-by: alanb
This commit is contained in:
parent
d3ecdcca36
commit
bfe32f271f
@ -81,7 +81,8 @@ $(eval $(call SetupNativeCompilation,BUILD_LIBNIO, \
|
||||
LDFLAGS_SUFFIX_windows := jvm.lib ws2_32.lib $(WIN_JAVA_LIB) \
|
||||
$(SUPPORT_OUTPUTDIR)/native/$(MODULE)/libnet/net.lib \
|
||||
advapi32.lib, \
|
||||
LDFLAGS_SUFFIX_macosx := -ljava -lnet -pthread -framework CoreFoundation, \
|
||||
LDFLAGS_SUFFIX_macosx := -ljava -lnet -pthread \
|
||||
-framework CoreFoundation -framework CoreServices, \
|
||||
LDFLAGS_SUFFIX :=, \
|
||||
VERSIONINFO_RESOURCE := $(GLOBAL_VERSION_INFO_RESOURCE), \
|
||||
RC_FLAGS := $(RC_FLAGS) \
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2015, 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
|
||||
@ -49,6 +49,8 @@ public class MacOSXFileSystemProvider extends BsdFileSystemProvider {
|
||||
FileTypeDetector getFileTypeDetector() {
|
||||
Path userMimeTypes = Paths.get(AccessController.doPrivileged(
|
||||
new GetPropertyAction("user.home")), ".mime.types");
|
||||
return new MimeTypesFileTypeDetector(userMimeTypes);
|
||||
|
||||
return chain(new MimeTypesFileTypeDetector(userMimeTypes),
|
||||
new UTIFileTypeDetector());
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedAction;
|
||||
|
||||
/**
|
||||
* File type detector that uses a file extension to look up its MIME type
|
||||
* via the Apple Uniform Type Identifier interfaces.
|
||||
*/
|
||||
class UTIFileTypeDetector extends AbstractFileTypeDetector {
|
||||
UTIFileTypeDetector() {
|
||||
super();
|
||||
}
|
||||
|
||||
private native String probe0(String fileExtension) throws IOException;
|
||||
|
||||
@Override
|
||||
protected String implProbeContentType(Path path) throws IOException {
|
||||
Path fn = path.getFileName();
|
||||
if (fn == null)
|
||||
return null; // no file name
|
||||
|
||||
String ext = getExtension(fn.toString());
|
||||
if (ext.isEmpty())
|
||||
return null; // no extension
|
||||
|
||||
return probe0(ext);
|
||||
}
|
||||
|
||||
static {
|
||||
AccessController.doPrivileged(new PrivilegedAction<>() {
|
||||
@Override
|
||||
public Void run() {
|
||||
System.loadLibrary("nio");
|
||||
return null;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
127
jdk/src/java.base/macosx/native/libnio/fs/UTIFileTypeDetector.c
Normal file
127
jdk/src/java.base/macosx/native/libnio/fs/UTIFileTypeDetector.c
Normal file
@ -0,0 +1,127 @@
|
||||
/*
|
||||
* Copyright (c) 2015, 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 <CoreFoundation/CoreFoundation.h>
|
||||
#include <CoreServices/CoreServices.h>
|
||||
|
||||
/**
|
||||
* Creates a CF string from the given Java string.
|
||||
* If javaString is NULL, NULL is returned.
|
||||
* If a memory error occurs, and OutOfMemoryError is thrown and
|
||||
* NULL is returned.
|
||||
*/
|
||||
static CFStringRef toCFString(JNIEnv *env, jstring javaString)
|
||||
{
|
||||
if (javaString == NULL) {
|
||||
return NULL;
|
||||
} else {
|
||||
CFStringRef result = NULL;
|
||||
jsize length = (*env)->GetStringLength(env, javaString);
|
||||
const jchar *chars = (*env)->GetStringChars(env, javaString, NULL);
|
||||
if (chars == NULL) {
|
||||
JNU_ThrowOutOfMemoryError(env, "toCFString failed");
|
||||
return NULL;
|
||||
}
|
||||
result = CFStringCreateWithCharacters(NULL, (const UniChar *)chars,
|
||||
length);
|
||||
(*env)->ReleaseStringChars(env, javaString, chars);
|
||||
if (result == NULL) {
|
||||
JNU_ThrowOutOfMemoryError(env, "toCFString failed");
|
||||
return NULL;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a Java string from the given CF string.
|
||||
* If cfString is NULL, NULL is returned.
|
||||
* If a memory error occurs, and OutOfMemoryError is thrown and
|
||||
* NULL is returned.
|
||||
*/
|
||||
static jstring toJavaString(JNIEnv *env, CFStringRef cfString)
|
||||
{
|
||||
if (cfString == NULL) {
|
||||
return NULL;
|
||||
} else {
|
||||
jstring javaString = NULL;
|
||||
|
||||
CFIndex length = CFStringGetLength(cfString);
|
||||
const UniChar *constchars = CFStringGetCharactersPtr(cfString);
|
||||
if (constchars) {
|
||||
javaString = (*env)->NewString(env, constchars, length);
|
||||
} else {
|
||||
UniChar *chars = malloc(length * sizeof(UniChar));
|
||||
if (chars == NULL) {
|
||||
JNU_ThrowOutOfMemoryError(env, "toJavaString failed");
|
||||
return NULL;
|
||||
}
|
||||
CFStringGetCharacters(cfString, CFRangeMake(0, length), chars);
|
||||
javaString = (*env)->NewString(env, chars, length);
|
||||
free(chars);
|
||||
}
|
||||
return javaString;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the content type corresponding to the supplied file extension.
|
||||
* The mapping is determined using Uniform Type Identifiers (UTIs). If
|
||||
* the file extension parameter is NULL, a CFString cannot be created
|
||||
* from the file extension parameter, there is no UTI corresponding to
|
||||
* the file extension, the UTI cannot supply a MIME type for the file
|
||||
* extension, or a Java string cannot be created, then NULL is returned;
|
||||
* otherwise the MIME type string is returned.
|
||||
*/
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_sun_nio_fs_UTIFileTypeDetector_probe0(JNIEnv* env, jobject ftd,
|
||||
jstring ext)
|
||||
{
|
||||
jstring result = NULL;
|
||||
|
||||
CFStringRef extension = toCFString(env, ext);
|
||||
if (extension != NULL) {
|
||||
CFStringRef uti =
|
||||
UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension,
|
||||
extension, NULL);
|
||||
CFRelease(extension);
|
||||
|
||||
if (uti != NULL) {
|
||||
CFStringRef mimeType =
|
||||
UTTypeCopyPreferredTagWithClass(uti, kUTTagClassMIMEType);
|
||||
CFRelease(uti);
|
||||
|
||||
if (mimeType != NULL) {
|
||||
result = toJavaString(env, mimeType);
|
||||
CFRelease(mimeType);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2015, 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
|
||||
@ -41,6 +41,27 @@ public abstract class AbstractFileTypeDetector
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the extension of a file name, specifically the portion of the
|
||||
* parameter string after the first dot. If the parameter is {@code null},
|
||||
* empty, does not contain a dot, or the dot is the last character, then an
|
||||
* empty string is returned, otherwise the characters after the dot are
|
||||
* returned.
|
||||
*
|
||||
* @param name A file name
|
||||
* @return The characters after the first dot or an empty string.
|
||||
*/
|
||||
protected final String getExtension(String name) {
|
||||
String ext = "";
|
||||
if (name != null && !name.isEmpty()) {
|
||||
int dot = name.indexOf('.');
|
||||
if ((dot >= 0) && (dot < name.length() - 1)) {
|
||||
ext = name.substring(dot + 1);
|
||||
}
|
||||
}
|
||||
return ext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Invokes the appropriate probe method to guess a file's content type,
|
||||
* and checks that the content type's syntax is valid.
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2015, 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
|
||||
@ -83,18 +83,6 @@ class MimeTypesFileTypeDetector extends AbstractFileTypeDetector {
|
||||
return mimeType;
|
||||
}
|
||||
|
||||
// Get the extension of a file name.
|
||||
private static String getExtension(String name) {
|
||||
String ext = "";
|
||||
if (name != null && !name.isEmpty()) {
|
||||
int dot = name.indexOf('.');
|
||||
if ((dot >= 0) && (dot < name.length() - 1)) {
|
||||
ext = name.substring(dot + 1);
|
||||
}
|
||||
}
|
||||
return ext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse the mime types file, and store the type-extension mappings into
|
||||
* mimeTypeMap. The mime types file is not loaded until the first probe
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2008, 2011, Oracle and/or its affiliates. All rights reserved.
|
||||
* Copyright (c) 2008, 2015, 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
|
||||
@ -22,7 +22,7 @@
|
||||
*/
|
||||
|
||||
/* @test
|
||||
* @bug 4313887
|
||||
* @bug 4313887 8129632
|
||||
* @summary Unit test for probeContentType method
|
||||
* @library ../..
|
||||
* @build Basic SimpleFileTypeDetector
|
||||
@ -33,9 +33,9 @@ import java.nio.file.*;
|
||||
import java.io.*;
|
||||
|
||||
/**
|
||||
* Uses Files.probeContentType to probe html file and custom file type.
|
||||
* Uses Files.probeContentType to probe html file, custom file type, and minimal
|
||||
* set of file extension to content type mappings.
|
||||
*/
|
||||
|
||||
public class Basic {
|
||||
|
||||
static Path createHtmlFile() throws IOException {
|
||||
@ -51,6 +51,39 @@ public class Basic {
|
||||
return Files.createTempFile("red", ".grape");
|
||||
}
|
||||
|
||||
static void checkContentTypes(String[] extensions, String[] expectedTypes)
|
||||
throws IOException {
|
||||
if (extensions.length != expectedTypes.length) {
|
||||
throw new IllegalArgumentException("Parameter array lengths differ");
|
||||
}
|
||||
|
||||
int failures = 0;
|
||||
for (int i = 0; i < extensions.length; i++) {
|
||||
String extension = extensions[i];
|
||||
Path file = Files.createTempFile("foo", "." + extension);
|
||||
try {
|
||||
String type = Files.probeContentType(file);
|
||||
if (type == null) {
|
||||
System.err.println("Content type of " + extension
|
||||
+ " cannot be determined");
|
||||
failures++;
|
||||
} else {
|
||||
if (!type.equals(expectedTypes[i])) {
|
||||
System.err.println("Content type: " + type
|
||||
+ "; expected: " + expectedTypes[i]);
|
||||
failures++;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
Files.delete(file);
|
||||
}
|
||||
}
|
||||
|
||||
if (failures > 0) {
|
||||
throw new RuntimeException("Test failed!");
|
||||
}
|
||||
}
|
||||
|
||||
public static void main(String[] args) throws IOException {
|
||||
|
||||
// exercise default file type detector
|
||||
@ -79,5 +112,17 @@ public class Basic {
|
||||
Files.delete(file);
|
||||
}
|
||||
|
||||
// Verify that common file extensions are mapped to the correct content
|
||||
// types on Mac OS X only which has consistent Uniform Type Identifiers.
|
||||
if (System.getProperty("os.name").contains("OS X")) {
|
||||
String[] extensions = new String[]{
|
||||
"jpg", "mp3", "mp4", "pdf", "png"
|
||||
};
|
||||
String[] expectedTypes = new String[]{
|
||||
"image/jpeg", "audio/mpeg", "video/mp4", "application/pdf",
|
||||
"image/png"
|
||||
};
|
||||
checkContentTypes(extensions, expectedTypes);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user