Prevent double calculation of containing class
[idea/community.git] / native / IdeaWin32 / IdeaWin32.cpp
1 #include "stdafx.h"
2 #include "IdeaWin32.h"
3 #include "jni_util.h"
4 #include "windows.h"
5
6 jfieldID nameId;
7
8 HANDLE FindFileInner(JNIEnv *env, jstring path, LPWIN32_FIND_DATA lpData) {
9         const jchar* str = env->GetStringChars(path, 0);
10         HANDLE h = FindFirstFile((LPCWSTR)str, lpData);
11         env->ReleaseStringChars(path, str);
12         return h;
13 }
14
15 bool CopyObjectArray(JNIEnv *env, jobjectArray dst, jobjectArray src,
16                          jint count)
17 {
18     int i;
19     for (i=0; i<count; i++) {
20         jobject p = env->GetObjectArrayElement(src, i);
21         env->SetObjectArrayElement(dst, i, p);
22         env->DeleteLocalRef(p);
23     }
24     return true;
25 }
26
27 static LONGLONG
28 fileTimeToInt64 (const FILETIME * time)
29 {
30     ULARGE_INTEGER _time;
31
32     _time.LowPart = time->dwLowDateTime;
33     _time.HighPart = time->dwHighDateTime;
34
35     return _time.QuadPart;
36 }
37
38 jfieldID nameID; 
39 jfieldID attributesID;
40 jfieldID timestampID;
41
42 jobject CreateFileInfo(JNIEnv *env, LPWIN32_FIND_DATA lpData, jclass cls) {
43
44         jobject o = env->AllocObject(cls);
45         if (o == NULL) {
46                 return NULL;
47         }
48         jstring fileName = env->NewString((jchar*)lpData->cFileName, (jsize)wcslen(lpData->cFileName));
49         if (fileName == NULL) {
50                 return NULL;
51         }
52         env->SetObjectField(o, nameID, fileName);
53         env->SetIntField(o, attributesID, lpData->dwFileAttributes);
54         env->SetLongField(o, timestampID, fileTimeToInt64(&lpData->ftLastWriteTime));
55         return o;
56 }
57
58 JNIEXPORT void JNICALL Java_com_intellij_openapi_vfs_impl_win32_FileInfo_initIDs(JNIEnv *env, jclass cls) {
59         nameID = env->GetFieldID(cls, "name", "Ljava/lang/String;");
60         attributesID = env->GetFieldID(cls, "attributes", "I");
61         timestampID = env->GetFieldID(cls, "timestamp", "J");
62 }
63
64 JNIEXPORT jobject JNICALL Java_com_intellij_openapi_vfs_impl_win32_IdeaWin32_getInfo(JNIEnv *env, jobject method, jstring path) {
65         WIN32_FIND_DATA data;
66         HANDLE h = FindFileInner(env, path, &data);
67         if (h == INVALID_HANDLE_VALUE) {
68           return NULL;
69         }
70         FindClose(h);   
71         jclass infoClass = env->FindClass("com/intellij/openapi/vfs/impl/win32/FileInfo");
72         return CreateFileInfo(env, &data, infoClass);
73 }
74
75 JNIEXPORT jobjectArray JNICALL Java_com_intellij_openapi_vfs_impl_win32_IdeaWin32_listChildren(JNIEnv *env, jobject method, jstring path)
76 {
77
78   WIN32_FIND_DATA data;
79   HANDLE h = FindFileInner(env, path, &data);
80   if (h == INVALID_HANDLE_VALUE) {
81           return NULL;
82   }
83
84   jobjectArray rv, old;
85   int len, maxlen;
86
87   len = 0;
88   maxlen = 16;
89   jclass infoClass = env->FindClass("com/intellij/openapi/vfs/impl/win32/FileInfo");
90   rv = env->NewObjectArray(maxlen, infoClass, NULL);
91   if (rv == NULL) goto error;
92   do  {
93         if (len == maxlen) {
94             old = rv;
95             rv = env->NewObjectArray(maxlen <<= 1,
96                                         infoClass, NULL);
97             if (rv == NULL) goto error;
98             if (!CopyObjectArray(env, rv, old, len)) goto error;
99             env->DeleteLocalRef(old);
100         }
101                 jobject o = CreateFileInfo(env, &data, infoClass);
102           env->SetObjectArrayElement(rv, len++, o);
103           env->DeleteLocalRef(o);
104   }
105   while (FindNextFile(h, &data));
106
107   FindClose(h); 
108
109         old = rv;
110         rv = env->NewObjectArray(len, infoClass, NULL);
111         if (rv == NULL) goto error;
112         if (!CopyObjectArray(env, rv, old, len)) goto error;
113         return rv;
114
115
116 error:
117   FindClose(h); 
118   return NULL;
119 }
120
121 BOOL APIENTRY DllMain( HMODULE hModule,
122                        DWORD  ul_reason_for_call,
123                        LPVOID lpReserved
124                                          )
125 {
126     return TRUE;
127 }
128