1/*
2 * Copyright (c) 2011, 2014, 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.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26
27#include <jni_util.h>
28
29#import "com_apple_laf_AquaFileView.h"
30
31#import <sys/param.h> // for MAXPATHLEN
32#import <CoreFoundation/CoreFoundation.h>
33#import <JavaNativeFoundation/JavaNativeFoundation.h>
34
35/*
36 * Class:     com_apple_laf_AquaFileView
37 * Method:    getNativePathToRunningJDKBundle
38 * Signature: ()Ljava/lang/String;
39 */
40// TODO: Un-comment this out
41/*JNIEXPORT jstring JNICALL Java_com_apple_laf_AquaFileView_getNativePathToRunningJDKBundle
42(JNIEnv *env, jclass clazz)
43{
44    jstring returnValue = NULL;
45JNF_COCOA_ENTER(env);
46
47    returnValue = JNFNSToJavaString(env, getRunningJavaBundle());
48
49JNF_COCOA_EXIT(env);
50    return returnValue;
51}*/
52
53/*
54 * Class:     com_apple_laf_AquaFileView
55 * Method:    getNativePathToSharedJDKBundle
56 * Signature: ()Ljava/lang/String;
57 */
58JNIEXPORT jstring JNICALL Java_com_apple_laf_AquaFileView_getNativePathToSharedJDKBundle
59(JNIEnv *env, jclass clazz)
60{
61    jstring returnValue = NULL;
62JNF_COCOA_ENTER(env);
63
64    returnValue = JNFNSToJavaString(env, [[NSBundle bundleWithIdentifier:@"com.apple.JavaVM"] bundlePath]);
65
66JNF_COCOA_EXIT(env);
67    return returnValue;
68}
69
70/*
71 * Class:     com_apple_laf_AquaFileView
72 * Method:    getNativeMachineName
73 * Signature: ()Ljava/lang/String;
74 */
75JNIEXPORT jstring JNICALL Java_com_apple_laf_AquaFileView_getNativeMachineName
76(JNIEnv *env, jclass clazz)
77{
78    jstring returnValue = NULL;
79JNF_COCOA_ENTER(env);
80
81    CFStringRef machineName = CSCopyMachineName();
82    returnValue = JNFNSToJavaString(env, (NSString*)machineName);
83
84    if (machineName != NULL) {
85        CFRelease(machineName);
86    }
87
88JNF_COCOA_EXIT(env);
89    return returnValue;
90}
91
92/*
93 * Class:     com_apple_laf_AquaFileView
94 * Method:    getNativeLSInfo
95 * Signature: ([BZ)I
96 */
97JNIEXPORT jint JNICALL Java_com_apple_laf_AquaFileView_getNativeLSInfo
98(JNIEnv *env, jclass clazz, jbyteArray absolutePath, jboolean isDir)
99{
100    jint returnValue = com_apple_laf_AquaFileView_UNINITALIZED_LS_INFO;
101JNF_COCOA_ENTER(env);
102
103    jbyte *byteArray = (*env)->GetByteArrayElements(env, absolutePath, NULL);
104    CHECK_NULL_RETURN(byteArray, returnValue);
105    jsize length = (*env)->GetArrayLength(env, absolutePath);
106
107    // Can't assume that byteArray is NULL terminated and FSPathMakeRef doesn't
108    // let us specify a length.
109    UInt8 arrayCopy[length + 1];
110    jsize i;
111    for (i = 0; i < length; i++) {
112        arrayCopy[i] = (UInt8)byteArray[i];
113    }
114    arrayCopy[length] = '\0';
115    (*env)->ReleaseByteArrayElements(env, absolutePath, byteArray, JNI_ABORT);
116
117    Boolean isDirectory = (isDir == JNI_TRUE ? true : false);
118    FSRef ref;
119    OSErr err = FSPathMakeRef((const UInt8 *)&arrayCopy, &ref, &isDirectory);
120    if (err == noErr) {
121        LSItemInfoRecord itemInfo;
122        err = LSCopyItemInfoForRef(&ref, kLSRequestBasicFlagsOnly, &itemInfo);
123
124        if (err == noErr) {
125            returnValue = itemInfo.flags;
126        }
127    }
128
129JNF_COCOA_EXIT(env);
130    return returnValue;
131}
132
133/*
134 * Class:     com_apple_laf_AquaFileView
135 * Method:    getNativeDisplayName
136 * Signature: ([BZ)Ljava/lang/String;
137 */
138JNIEXPORT jstring JNICALL Java_com_apple_laf_AquaFileView_getNativeDisplayName
139(JNIEnv *env, jclass clazz, jbyteArray absolutePath, jboolean isDir)
140{
141    jstring returnValue = NULL;
142JNF_COCOA_ENTER(env);
143
144    jbyte *byteArray = (*env)->GetByteArrayElements(env, absolutePath, NULL);
145    CHECK_NULL_RETURN(byteArray, returnValue);
146    jsize length = (*env)->GetArrayLength(env, absolutePath);
147
148    // Can't assume that byteArray is NULL terminated and FSPathMakeRef doesn't
149    // let us specify a length.
150    UInt8 arrayCopy[length + 1];
151    jsize i;
152    for (i = 0; i < length; i++) {
153        arrayCopy[i] = (UInt8)byteArray[i];
154    }
155    arrayCopy[length] = '\0';
156    (*env)->ReleaseByteArrayElements(env, absolutePath, byteArray, JNI_ABORT);
157
158    Boolean isDirectory = (isDir == JNI_TRUE ? true : false);
159    FSRef ref;
160
161    OSErr theErr = FSPathMakeRefWithOptions((const UInt8 *)&arrayCopy,
162                                            kFSPathMakeRefDoNotFollowLeafSymlink,
163                                            &ref, &isDirectory);
164    if (theErr == noErr) {
165        CFStringRef displayName = NULL;
166
167        theErr = LSCopyDisplayNameForRef(&ref, &displayName);
168
169        if (theErr == noErr) {
170            CFMutableStringRef mutableDisplayName = CFStringCreateMutableCopy(NULL, 0, displayName);
171            CFStringNormalize(mutableDisplayName, kCFStringNormalizationFormC);
172            returnValue = JNFNSToJavaString(env, (NSString *)mutableDisplayName);
173            CFRelease(mutableDisplayName);
174        }
175
176        if (displayName != NULL) {
177            CFRelease(displayName);
178        }
179    }
180
181JNF_COCOA_EXIT(env);
182    return returnValue;
183}
184
185/*
186 * Class:     com_apple_laf_AquaFileView
187 * Method:    getNativePathForResolvedAlias
188 * Signature: ([BZ)Ljava/lang/String;
189 */
190JNIEXPORT jstring JNICALL Java_com_apple_laf_AquaFileView_getNativePathForResolvedAlias
191(JNIEnv *env, jclass clazz, jbyteArray pathToAlias, jboolean isDir)
192{
193    jstring returnValue = NULL;
194JNF_COCOA_ENTER(env);
195
196    UInt8 pathCString[MAXPATHLEN + 1];
197    size_t maxPathLen = sizeof(pathCString) - 1;
198
199    jbyte *byteArray = (*env)->GetByteArrayElements(env, pathToAlias, NULL);
200    CHECK_NULL_RETURN(byteArray, returnValue);
201    jsize length = (*env)->GetArrayLength(env, pathToAlias);
202
203    if (length > maxPathLen) {
204        length = maxPathLen;
205    }
206    strncpy((char *)pathCString, (char *)byteArray, length);
207    // make sure it's null terminated
208    pathCString[length] = '\0';
209    (*env)->ReleaseByteArrayElements(env, pathToAlias, byteArray, JNI_ABORT);
210
211    Boolean isDirectory = (isDir == JNI_TRUE ? true : false);
212    FSRef fileRef;
213    OSErr theErr = FSPathMakeRef(pathCString, &fileRef, &isDirectory);
214
215    Boolean ignored;
216    theErr = FSResolveAliasFileWithMountFlags(&fileRef, false, &ignored,
217                                              &ignored, kResolveAliasFileNoUI);
218    if (theErr == noErr) {
219        UInt8 resolvedPath[MAXPATHLEN];
220        theErr = FSRefMakePath(&fileRef, resolvedPath, MAXPATHLEN);
221
222        if (theErr == noErr) {
223            returnValue = (*env)->NewStringUTF(env, (char *)resolvedPath);
224        }
225    }
226
227JNF_COCOA_EXIT(env);
228    return returnValue;
229}
230