pylucene 3.5.0-3
[pylucene.git] / lucene-java-3.5.0 / lucene / contrib / misc / src / java / org / apache / lucene / store / WindowsDirectory.cpp
1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with this
4  * work for additional information regarding copyright ownership. The ASF
5  * licenses this file to You under the Apache License, Version 2.0 (the
6  * "License"); you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  * 
9  * http://www.apache.org/licenses/LICENSE-2.0
10  * 
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13  * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
14  * License for the specific language governing permissions and limitations under
15  * the License.
16  */
17  
18 #include <jni.h>
19 #include "windows.h"
20
21 /**
22  * Windows Native IO methods.
23  */
24 extern "C" {
25
26 /**
27  * Utility to format a Windows system error code into an exception.
28  */
29 void throwIOException(JNIEnv *env, DWORD error) 
30 {
31   jclass ioex;
32   char *msg;
33   
34   ioex = env->FindClass("java/io/IOException");
35   
36   if (ioex != NULL) {
37     FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
38                   NULL, error, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR) &msg, 0, NULL );
39     env->ThrowNew(ioex, msg);
40     LocalFree(msg);
41   }
42 }
43
44 /**
45  * Utility to throw Exceptions on bad input
46  */
47 void throwException(JNIEnv *env, const char *clazz, const char *msg) 
48 {
49   jclass exc = env->FindClass(clazz);
50   
51   if (exc != NULL) {
52     env->ThrowNew(exc, msg);
53   }
54 }
55
56 /**
57  * Opens a handle to a file.
58  *
59  * Class:     org_apache_lucene_store_WindowsDirectory
60  * Method:    open
61  * Signature: (Ljava/lang/String;)J
62  */
63 JNIEXPORT jlong JNICALL Java_org_apache_lucene_store_WindowsDirectory_open
64   (JNIEnv *env, jclass ignored, jstring filename) 
65 {
66   char *fname;
67   HANDLE handle;
68   
69   if (filename == NULL) {
70     throwException(env, "java/lang/NullPointerException", "filename cannot be null");
71     return -1;
72   }
73   
74   fname = (char *) env->GetStringUTFChars(filename, NULL);
75   
76   if (fname == NULL) {
77     throwException(env, "java/lang/IllegalArgumentException", "invalid filename");
78     return -1;
79   }
80   
81   handle = CreateFile(fname, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, 
82                       NULL, OPEN_EXISTING, FILE_FLAG_RANDOM_ACCESS, NULL);
83   
84   env->ReleaseStringUTFChars(filename, fname);
85   
86   if (handle == INVALID_HANDLE_VALUE) {
87     throwIOException(env, GetLastError());
88     return -1;
89   }
90
91   return (jlong) handle;
92 }
93
94 /** 
95  * Reads data into the byte array, starting at offset, for length characters.
96  * The read is positioned at pos.
97  * 
98  * Class:     org_apache_lucene_store_WindowsDirectory
99  * Method:    read
100  * Signature: (J[BIIJ)I
101  */
102 JNIEXPORT jint JNICALL Java_org_apache_lucene_store_WindowsDirectory_read
103   (JNIEnv *env, jclass ignored, jlong fd, jbyteArray bytes, jint offset, jint length, jlong pos)
104 {
105   OVERLAPPED io = { 0 };
106   DWORD numRead = -1;
107   
108   io.Offset = (DWORD) (pos & 0xFFFFFFFF);
109   io.OffsetHigh = (DWORD) ((pos >> 0x20) & 0x7FFFFFFF);
110   
111   if (bytes == NULL) {
112     throwException(env, "java/lang/NullPointerException", "bytes cannot be null");
113     return -1;
114   }
115   
116   if (length <= 4096) {  /* For small buffers, avoid GetByteArrayElements' copy */
117     char buffer[length];
118         
119     if (ReadFile((HANDLE) fd, &buffer, length, &numRead, &io)) {
120       env->SetByteArrayRegion(bytes, offset, numRead, (const jbyte *) buffer);
121     } else {
122       throwIOException(env, GetLastError());
123       numRead = -1;
124     }
125         
126   } else {
127     jbyte *buffer = env->GetByteArrayElements (bytes, NULL);
128   
129     if (!ReadFile((HANDLE) fd, (void *)(buffer+offset), length, &numRead, &io)) {
130       throwIOException(env, GetLastError());
131       numRead = -1;
132     }
133         
134     env->ReleaseByteArrayElements(bytes, buffer, numRead == 0 || numRead == -1 ? JNI_ABORT : 0);
135   }
136   
137   return numRead;
138 }
139
140 /**
141  * Closes a handle to a file
142  *
143  * Class:     org_apache_lucene_store_WindowsDirectory
144  * Method:    close
145  * Signature: (J)V
146  */
147 JNIEXPORT void JNICALL Java_org_apache_lucene_store_WindowsDirectory_close
148   (JNIEnv *env, jclass ignored, jlong fd) 
149 {
150   if (!CloseHandle((HANDLE) fd)) {
151     throwIOException(env, GetLastError());
152   }
153 }
154
155 /**
156  * Returns the length in bytes of a file.
157  *
158  * Class:     org_apache_lucene_store_WindowsDirectory
159  * Method:    length
160  * Signature: (J)J
161  */
162 JNIEXPORT jlong JNICALL Java_org_apache_lucene_store_WindowsDirectory_length
163   (JNIEnv *env, jclass ignored, jlong fd)
164 {
165   BY_HANDLE_FILE_INFORMATION info;
166         
167   if (GetFileInformationByHandle((HANDLE) fd, (LPBY_HANDLE_FILE_INFORMATION) &info)) {
168     return (jlong) (((DWORDLONG) info.nFileSizeHigh << 0x20) + info.nFileSizeLow);
169   } else {
170     throwIOException(env, GetLastError());
171     return -1;
172   }
173 }
174
175 } /* extern "C" */