1 : /******************************************************************************
2 : * $Id: ogrmdbjackcess.cpp 22156 2011-04-13 20:08:07Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Implements OGRMDBJavaEnv class.
6 : * Author: Even Rouault, <even dot rouault at mines dash paris dot org>
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2011, Even Rouault, <even dot rouault at mines dash paris dot org>
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 :
30 : #include "ogr_mdb.h"
31 :
32 : CPL_CVSID("$Id: ogrmdbjackcess.cpp 22156 2011-04-13 20:08:07Z rouault $");
33 :
34 : static JavaVM *jvm_static = NULL;
35 : static JNIEnv *env_static = NULL;
36 :
37 : /************************************************************************/
38 : /* OGRMDBJavaEnv() */
39 : /************************************************************************/
40 :
41 12 : OGRMDBJavaEnv::OGRMDBJavaEnv()
42 : {
43 12 : jvm = NULL;
44 12 : env = NULL;
45 12 : bCalledFromJava = FALSE;
46 :
47 12 : byteArray_class = NULL;
48 :
49 12 : file_class = NULL;
50 12 : file_constructor = NULL;
51 12 : database_class = NULL;
52 12 : database_open = NULL;
53 12 : database_close = NULL;
54 12 : database_getTableNames = NULL;
55 12 : database_getTable = NULL;
56 :
57 12 : table_class = NULL;
58 12 : table_getColumns = NULL;
59 12 : table_iterator = NULL;
60 12 : table_getRowCount = NULL;
61 :
62 12 : column_class = NULL;
63 12 : column_getName = NULL;
64 12 : column_getType = NULL;
65 12 : column_getLength = NULL;
66 12 : column_isVariableLength = NULL;
67 :
68 12 : datatype_class = NULL;
69 12 : datatype_getValue = NULL;
70 :
71 12 : list_class = NULL;
72 12 : list_iterator = NULL;
73 :
74 12 : set_class = NULL;
75 12 : set_iterator = NULL;
76 :
77 12 : map_class = NULL;
78 12 : map_get = NULL;
79 :
80 12 : iterator_class = NULL;
81 12 : iterator_hasNext = NULL;
82 12 : iterator_next = NULL;
83 :
84 12 : object_class = NULL;
85 12 : object_toString = NULL;
86 12 : object_getClass = NULL;
87 :
88 12 : boolean_class = NULL;
89 12 : boolean_booleanValue = NULL;
90 :
91 12 : byte_class = NULL;
92 12 : byte_byteValue = NULL;
93 :
94 12 : short_class = NULL;
95 12 : short_shortValue = NULL;
96 :
97 12 : integer_class = NULL;
98 12 : integer_intValue = NULL;
99 :
100 12 : float_class = NULL;
101 12 : float_floatValue = NULL;
102 :
103 12 : double_class = NULL;
104 12 : double_doubleValue = NULL;
105 12 : }
106 :
107 : /************************************************************************/
108 : /* ~OGRMDBJavaEnv() */
109 : /************************************************************************/
110 :
111 12 : OGRMDBJavaEnv::~OGRMDBJavaEnv()
112 : {
113 12 : if (jvm)
114 : {
115 12 : env->DeleteLocalRef(byteArray_class);
116 :
117 12 : env->DeleteLocalRef(file_class);
118 12 : env->DeleteLocalRef(database_class);
119 :
120 12 : env->DeleteLocalRef(table_class);
121 :
122 12 : env->DeleteLocalRef(column_class);
123 :
124 12 : env->DeleteLocalRef(datatype_class);
125 :
126 12 : env->DeleteLocalRef(list_class);
127 :
128 12 : env->DeleteLocalRef(set_class);
129 :
130 12 : env->DeleteLocalRef(map_class);
131 :
132 12 : env->DeleteLocalRef(iterator_class);
133 :
134 12 : env->DeleteLocalRef(object_class);
135 :
136 12 : env->DeleteLocalRef(boolean_class);
137 12 : env->DeleteLocalRef(byte_class);
138 12 : env->DeleteLocalRef(short_class);
139 12 : env->DeleteLocalRef(integer_class);
140 12 : env->DeleteLocalRef(float_class);
141 12 : env->DeleteLocalRef(double_class);
142 :
143 : /*if (!bCalledFromJava)
144 : {
145 : CPLDebug("MDB", "Destroying JVM");
146 : int ret = jvm->DestroyJavaVM();
147 : CPLDebug("MDB", "ret=%d", ret);
148 : }*/
149 : }
150 12 : }
151 :
152 : #define CHECK(x, y) do {x = y; if (!x) { CPLError(CE_Failure, CPLE_AppDefined, #y " failed"); return FALSE;} } while(0)
153 :
154 : /************************************************************************/
155 : /* Init() */
156 : /************************************************************************/
157 :
158 12 : int OGRMDBJavaEnv::Init()
159 : {
160 12 : if (jvm_static == NULL)
161 : {
162 : JavaVM* vmBuf[1];
163 : jsize nVMs;
164 :
165 : /* Are we already called from Java ? */
166 6 : if (JNI_GetCreatedJavaVMs(vmBuf, 1, &nVMs) == JNI_OK && nVMs == 1)
167 : {
168 0 : jvm = vmBuf[0];
169 0 : if (jvm->GetEnv((void **)&env, JNI_VERSION_1_2) == JNI_OK)
170 : {
171 0 : bCalledFromJava = TRUE;
172 : }
173 : else
174 : {
175 0 : jvm = NULL;
176 0 : env = NULL;
177 : }
178 : }
179 : else
180 : {
181 : JavaVMInitArgs args;
182 : JavaVMOption options[1];
183 6 : args.version = JNI_VERSION_1_2;
184 6 : const char* pszClassPath = CPLGetConfigOption("CLASSPATH", NULL);
185 6 : CPLString osClassPathOption;
186 6 : if (pszClassPath)
187 : {
188 6 : args.nOptions = 1;
189 6 : osClassPathOption.Printf("-Djava.class.path=%s", pszClassPath);
190 6 : options[0].optionString = (char*) osClassPathOption.c_str();
191 6 : args.options = options;
192 : }
193 : else
194 0 : args.nOptions = 0;
195 6 : args.ignoreUnrecognized = JNI_FALSE;
196 :
197 6 : int ret = JNI_CreateJavaVM(&jvm, (void **)&env, &args);
198 6 : if (ret != 0 || jvm == NULL || env == NULL)
199 : {
200 0 : CPLError(CE_Failure, CPLE_AppDefined, "JNI_CreateJavaVM failed (%d)", ret);
201 0 : return FALSE;
202 : }
203 :
204 6 : jvm_static = jvm;
205 6 : env_static = env;
206 : }
207 : }
208 : else
209 : {
210 6 : jvm = jvm_static;
211 6 : env = env_static;
212 : }
213 :
214 12 : CHECK(byteArray_class, env->FindClass("[B"));
215 12 : CHECK(file_class, env->FindClass("java/io/File"));
216 12 : CHECK(file_constructor, env->GetMethodID(file_class, "<init>", "(Ljava/lang/String;)V"));
217 12 : CHECK(database_class, env->FindClass("com/healthmarketscience/jackcess/Database"));
218 :
219 12 : CHECK(database_open, env->GetStaticMethodID(database_class, "open", "(Ljava/io/File;Z)Lcom/healthmarketscience/jackcess/Database;"));
220 12 : CHECK(database_close, env->GetMethodID(database_class, "close", "()V"));
221 12 : CHECK(database_getTableNames, env->GetMethodID(database_class, "getTableNames", "()Ljava/util/Set;"));
222 12 : CHECK(database_getTable, env->GetMethodID(database_class, "getTable", "(Ljava/lang/String;)Lcom/healthmarketscience/jackcess/Table;"));
223 :
224 12 : CHECK(table_class, env->FindClass("com/healthmarketscience/jackcess/Table"));
225 12 : CHECK(table_getColumns, env->GetMethodID(table_class, "getColumns", "()Ljava/util/List;"));
226 12 : CHECK(table_iterator, env->GetMethodID(table_class, "iterator", "()Ljava/util/Iterator;"));
227 12 : CHECK(table_getRowCount, env->GetMethodID(table_class, "getRowCount", "()I"));
228 :
229 12 : CHECK(column_class, env->FindClass("com/healthmarketscience/jackcess/Column"));
230 12 : CHECK(column_getName, env->GetMethodID(column_class, "getName", "()Ljava/lang/String;"));
231 12 : CHECK(column_getType, env->GetMethodID(column_class, "getType", "()Lcom/healthmarketscience/jackcess/DataType;"));
232 12 : CHECK(column_getLength, env->GetMethodID(column_class, "getLength", "()S"));
233 12 : CHECK(column_isVariableLength, env->GetMethodID(column_class, "isVariableLength", "()Z"));
234 :
235 12 : CHECK(datatype_class, env->FindClass("com/healthmarketscience/jackcess/DataType"));
236 12 : CHECK(datatype_getValue, env->GetMethodID(datatype_class, "getValue", "()B"));
237 :
238 12 : CHECK(list_class, env->FindClass("java/util/List"));
239 12 : CHECK(list_iterator, env->GetMethodID(list_class, "iterator", "()Ljava/util/Iterator;"));
240 :
241 12 : CHECK(set_class, env->FindClass("java/util/Set"));
242 12 : CHECK(set_iterator, env->GetMethodID(set_class, "iterator", "()Ljava/util/Iterator;"));
243 :
244 12 : CHECK(map_class, env->FindClass("java/util/Map"));
245 12 : CHECK(map_get, env->GetMethodID(map_class, "get", "(Ljava/lang/Object;)Ljava/lang/Object;"));
246 :
247 12 : CHECK(iterator_class, env->FindClass("java/util/Iterator"));
248 12 : CHECK(iterator_hasNext, env->GetMethodID(iterator_class, "hasNext", "()Z"));
249 12 : CHECK(iterator_next, env->GetMethodID(iterator_class, "next", "()Ljava/lang/Object;"));
250 :
251 12 : CHECK(object_class, env->FindClass("java/lang/Object"));
252 12 : CHECK(object_toString, env->GetMethodID(object_class, "toString", "()Ljava/lang/String;"));
253 12 : CHECK(object_getClass, env->GetMethodID(object_class, "getClass", "()Ljava/lang/Class;"));
254 :
255 12 : CHECK(boolean_class, env->FindClass("java/lang/Boolean"));
256 12 : CHECK(boolean_booleanValue, env->GetMethodID(boolean_class, "booleanValue", "()Z"));
257 :
258 12 : CHECK(byte_class, env->FindClass("java/lang/Byte"));
259 12 : CHECK(byte_byteValue, env->GetMethodID(byte_class, "byteValue", "()B"));
260 :
261 12 : CHECK(short_class, env->FindClass("java/lang/Short"));
262 12 : CHECK(short_shortValue, env->GetMethodID(short_class, "shortValue", "()S"));
263 :
264 12 : CHECK(integer_class, env->FindClass("java/lang/Integer"));
265 12 : CHECK(integer_intValue, env->GetMethodID(integer_class, "intValue", "()I"));
266 :
267 12 : CHECK(float_class, env->FindClass("java/lang/Float"));
268 12 : CHECK(float_floatValue, env->GetMethodID(float_class, "floatValue", "()F"));
269 :
270 12 : CHECK(double_class, env->FindClass("java/lang/Double"));
271 12 : CHECK(double_doubleValue, env->GetMethodID(integer_class, "doubleValue", "()D"));
272 :
273 12 : return TRUE;
274 : }
275 :
276 :
277 : /************************************************************************/
278 : /* ExceptionOccured() */
279 : /************************************************************************/
280 :
281 7891046 : int OGRMDBJavaEnv::ExceptionOccured()
282 : {
283 7891046 : jthrowable exc = env->ExceptionOccurred();
284 7891046 : if (exc)
285 : {
286 0 : env->ExceptionDescribe();
287 0 : env->ExceptionClear();
288 0 : return TRUE;
289 : }
290 7891046 : return FALSE;
291 : }
292 :
293 :
294 : /************************************************************************/
295 : /* OGRMDBDatabase() */
296 : /************************************************************************/
297 :
298 12 : OGRMDBDatabase::OGRMDBDatabase()
299 : {
300 12 : env = NULL;
301 12 : database = NULL;
302 12 : }
303 :
304 : /************************************************************************/
305 : /* ~OGRMDBDatabase() */
306 : /************************************************************************/
307 :
308 12 : OGRMDBDatabase::~OGRMDBDatabase()
309 : {
310 12 : if (database)
311 : {
312 12 : CPLDebug("MDB", "Closing database");
313 12 : env->env->CallVoidMethod(database, env->database_close);
314 :
315 12 : env->env->DeleteGlobalRef(database);
316 : }
317 12 : }
318 :
319 : /************************************************************************/
320 : /* Open() */
321 : /************************************************************************/
322 :
323 12 : OGRMDBDatabase* OGRMDBDatabase::Open(OGRMDBJavaEnv* env, const char* pszName)
324 : {
325 12 : jstring jstr = env->env->NewStringUTF(pszName);
326 12 : jobject file = env->env->NewObject(env->file_class, env->file_constructor, jstr);
327 12 : if (env->ExceptionOccured()) return NULL;
328 12 : env->env->ReleaseStringUTFChars(jstr, NULL);
329 :
330 12 : jobject database = env->env->CallStaticObjectMethod(env->database_class, env->database_open, file, JNI_TRUE);
331 :
332 12 : env->env->DeleteLocalRef(file);
333 :
334 12 : if (env->ExceptionOccured()) return NULL;
335 12 : if (database == NULL)
336 0 : return NULL;
337 :
338 12 : OGRMDBDatabase* poDB = new OGRMDBDatabase();
339 12 : poDB->env = env;
340 12 : poDB->database = env->env->NewGlobalRef(database);
341 12 : env->env->DeleteLocalRef(database);
342 12 : return poDB;
343 : }
344 :
345 : /************************************************************************/
346 : /* FetchTableNames() */
347 : /************************************************************************/
348 :
349 12 : int OGRMDBDatabase::FetchTableNames()
350 : {
351 12 : if (env->bCalledFromJava)
352 0 : env->Init();
353 :
354 12 : jobject table_set = env->env->CallObjectMethod(database, env->database_getTableNames);
355 12 : if (env->ExceptionOccured()) return FALSE;
356 12 : jobject iterator = env->env->CallObjectMethod(table_set, env->set_iterator);
357 12 : if (env->ExceptionOccured()) return FALSE;
358 :
359 480 : while( env->env->CallBooleanMethod(iterator, env->iterator_hasNext) )
360 : {
361 456 : if (env->ExceptionOccured()) return FALSE;
362 456 : jstring table_name_jstring = (jstring) env->env->CallObjectMethod(iterator, env->iterator_next);
363 456 : if (env->ExceptionOccured()) return FALSE;
364 : jboolean is_copy;
365 456 : const char* table_name_str = env->env->GetStringUTFChars(table_name_jstring, &is_copy);
366 :
367 456 : apoTableNames.push_back(table_name_str);
368 : //CPLDebug("MDB", "Table %s", table_name_str);
369 :
370 456 : env->env->ReleaseStringUTFChars(table_name_jstring, table_name_str);
371 456 : env->env->DeleteLocalRef(table_name_jstring);
372 : }
373 12 : env->env->DeleteLocalRef(iterator);
374 12 : env->env->DeleteLocalRef(table_set);
375 12 : return TRUE;
376 : }
377 :
378 : /************************************************************************/
379 : /* GetTable() */
380 : /************************************************************************/
381 :
382 84 : OGRMDBTable* OGRMDBDatabase::GetTable(const char* pszTableName)
383 : {
384 84 : if (env->bCalledFromJava)
385 0 : env->Init();
386 :
387 84 : jstring table_name_jstring = env->env->NewStringUTF(pszTableName);
388 84 : jobject table = env->env->CallObjectMethod(database, env->database_getTable, table_name_jstring);
389 84 : if (env->ExceptionOccured()) return NULL;
390 84 : env->env->DeleteLocalRef(table_name_jstring);
391 :
392 84 : if (!table)
393 0 : return NULL;
394 :
395 84 : jobject global_table = env->env->NewGlobalRef(table);
396 84 : env->env->DeleteLocalRef(table);
397 84 : table = global_table;
398 :
399 84 : OGRMDBTable* poTable = new OGRMDBTable(env, this, table, pszTableName);
400 84 : if (!poTable->FetchColumns())
401 : {
402 0 : delete poTable;
403 0 : return NULL;
404 : }
405 84 : return poTable;
406 : }
407 :
408 : /************************************************************************/
409 : /* OGRMDBTable() */
410 : /************************************************************************/
411 :
412 84 : OGRMDBTable::OGRMDBTable(OGRMDBJavaEnv* env, OGRMDBDatabase* poDB, jobject table, const char* pszTableName )
413 : {
414 84 : this->env = env;
415 84 : this->poDB = poDB;
416 84 : this->table = table;
417 84 : osTableName = pszTableName;
418 84 : table_iterator_obj = NULL;
419 84 : row = NULL;
420 84 : }
421 :
422 : /************************************************************************/
423 : /* ~OGRMDBTable() */
424 : /************************************************************************/
425 :
426 84 : OGRMDBTable::~OGRMDBTable()
427 : {
428 84 : if (env)
429 : {
430 : //CPLDebug("MDB", "Freeing table %s", osTableName.c_str());
431 84 : if (env->bCalledFromJava)
432 0 : env->Init();
433 :
434 : int i;
435 996 : for(i=0;i<(int)apoColumnNameObjects.size();i++)
436 912 : env->env->DeleteGlobalRef(apoColumnNameObjects[i]);
437 :
438 84 : env->env->DeleteGlobalRef(table_iterator_obj);
439 84 : env->env->DeleteGlobalRef(row);
440 84 : env->env->DeleteGlobalRef(table);
441 : }
442 84 : }
443 :
444 : /************************************************************************/
445 : /* FetchColumns() */
446 : /************************************************************************/
447 :
448 84 : int OGRMDBTable::FetchColumns()
449 : {
450 84 : if (env->bCalledFromJava)
451 0 : env->Init();
452 :
453 84 : jobject column_lists = env->env->CallObjectMethod(table, env->table_getColumns);
454 84 : if (env->ExceptionOccured()) return FALSE;
455 :
456 84 : jobject iterator_cols = env->env->CallObjectMethod(column_lists, env->list_iterator);
457 84 : if (env->ExceptionOccured()) return FALSE;
458 :
459 1080 : while( env->env->CallBooleanMethod(iterator_cols, env->iterator_hasNext) )
460 : {
461 912 : if (env->ExceptionOccured()) return FALSE;
462 :
463 912 : jobject column = env->env->CallObjectMethod(iterator_cols, env->iterator_next);
464 912 : if (env->ExceptionOccured()) return FALSE;
465 :
466 912 : jstring column_name_jstring = (jstring) env->env->CallObjectMethod(column, env->column_getName);
467 912 : if (env->ExceptionOccured()) return FALSE;
468 : jboolean is_copy;
469 912 : const char* column_name_str = env->env->GetStringUTFChars(column_name_jstring, &is_copy);
470 912 : apoColumnNames.push_back(column_name_str);
471 912 : env->env->ReleaseStringUTFChars(column_name_jstring, column_name_str);
472 :
473 912 : apoColumnNameObjects.push_back((jstring) env->env->NewGlobalRef(column_name_jstring));
474 912 : env->env->DeleteLocalRef(column_name_jstring);
475 :
476 912 : jobject column_type = env->env->CallObjectMethod(column, env->column_getType);
477 912 : if (env->ExceptionOccured()) return FALSE;
478 912 : int type = env->env->CallByteMethod(column_type, env->datatype_getValue);
479 912 : if (env->ExceptionOccured()) return FALSE;
480 912 : apoColumnTypes.push_back(type);
481 :
482 912 : int isvariablelength = env->env->CallBooleanMethod(column, env->column_isVariableLength);
483 912 : if (env->ExceptionOccured()) return FALSE;
484 912 : if (!isvariablelength)
485 : {
486 720 : int length = env->env->CallShortMethod(column, env->column_getLength);
487 720 : if (env->ExceptionOccured()) return FALSE;
488 720 : apoColumnLengths.push_back(length);
489 : }
490 : else
491 192 : apoColumnLengths.push_back(0);
492 :
493 : //CPLDebug("MDB", "Column %s, type = %d", apoColumnNames[apoColumnNames.size()-1].c_str(), type);
494 :
495 912 : env->env->DeleteLocalRef(column_type);
496 :
497 912 : env->env->DeleteLocalRef(column);
498 : }
499 84 : env->env->DeleteLocalRef(iterator_cols);
500 84 : env->env->DeleteLocalRef(column_lists);
501 :
502 84 : return TRUE;
503 : }
504 :
505 : /************************************************************************/
506 : /* ResetReading() */
507 : /************************************************************************/
508 :
509 248 : void OGRMDBTable::ResetReading()
510 : {
511 248 : if (env->bCalledFromJava)
512 0 : env->Init();
513 :
514 248 : env->env->DeleteGlobalRef(table_iterator_obj);
515 248 : table_iterator_obj = NULL;
516 248 : env->env->DeleteGlobalRef(row);
517 248 : row = NULL;
518 248 : }
519 :
520 : /************************************************************************/
521 : /* GetNextRow() */
522 : /************************************************************************/
523 :
524 415098 : int OGRMDBTable::GetNextRow()
525 : {
526 415098 : if (env->bCalledFromJava)
527 0 : env->Init();
528 :
529 415098 : if (table_iterator_obj == NULL)
530 : {
531 178 : table_iterator_obj = env->env->CallObjectMethod(table, env->table_iterator);
532 178 : if (env->ExceptionOccured()) return FALSE;
533 178 : if (table_iterator_obj)
534 : {
535 178 : jobject global_table_iterator_obj = env->env->NewGlobalRef(table_iterator_obj);
536 178 : env->env->DeleteLocalRef(table_iterator_obj);
537 178 : table_iterator_obj = global_table_iterator_obj;
538 : }
539 : }
540 415098 : if (table_iterator_obj == NULL)
541 0 : return FALSE;
542 :
543 415098 : if (!env->env->CallBooleanMethod(table_iterator_obj, env->iterator_hasNext))
544 90 : return FALSE;
545 415008 : if (env->ExceptionOccured()) return FALSE;
546 :
547 415008 : if (row)
548 : {
549 414830 : env->env->DeleteGlobalRef(row);
550 414830 : row = NULL;
551 : }
552 :
553 415008 : row = env->env->CallObjectMethod(table_iterator_obj, env->iterator_next);
554 415008 : if (env->ExceptionOccured()) return FALSE;
555 415008 : if (row == NULL)
556 0 : return FALSE;
557 :
558 415008 : jobject global_row = env->env->NewGlobalRef(row);
559 415008 : env->env->DeleteLocalRef(row);
560 415008 : row = global_row;
561 :
562 415008 : return TRUE;
563 : }
564 :
565 : /************************************************************************/
566 : /* GetColumnVal() */
567 : /************************************************************************/
568 :
569 3319236 : jobject OGRMDBTable::GetColumnVal(int iCol)
570 : {
571 3319236 : if (row == NULL)
572 0 : return NULL;
573 :
574 3319236 : jobject val = env->env->CallObjectMethod(row, env->map_get, apoColumnNameObjects[iCol]);
575 3319236 : if (env->ExceptionOccured()) return NULL;
576 3319236 : return val;
577 : }
578 :
579 : /************************************************************************/
580 : /* GetColumnAsString() */
581 : /************************************************************************/
582 :
583 2489076 : char* OGRMDBTable::GetColumnAsString(int iCol)
584 : {
585 2489076 : jobject val = GetColumnVal(iCol);
586 2489076 : if (!val) return NULL;
587 :
588 2489076 : jstring val_jstring = (jstring) env->env->CallObjectMethod(val, env->object_toString);
589 2489076 : if (env->ExceptionOccured()) return NULL;
590 : jboolean is_copy;
591 2489076 : const char* val_str = env->env->GetStringUTFChars(val_jstring, &is_copy);
592 2489076 : char* dup_str = (val_str) ? CPLStrdup(val_str) : NULL;
593 2489076 : env->env->ReleaseStringUTFChars(val_jstring, val_str);
594 2489076 : env->env->DeleteLocalRef(val_jstring);
595 :
596 2489076 : env->env->DeleteLocalRef(val);
597 :
598 2489076 : return dup_str;
599 : }
600 :
601 : /************************************************************************/
602 : /* GetColumnAsInt() */
603 : /************************************************************************/
604 :
605 415080 : int OGRMDBTable::GetColumnAsInt(int iCol)
606 : {
607 415080 : jobject val = GetColumnVal(iCol);
608 415080 : if (!val) return 0;
609 :
610 415080 : int int_val = 0;
611 415080 : if (apoColumnTypes[iCol] == MDB_Boolean)
612 36 : int_val = env->env->CallBooleanMethod(val, env->boolean_booleanValue);
613 415044 : else if (apoColumnTypes[iCol] == MDB_Byte)
614 0 : int_val = env->env->CallByteMethod(val, env->byte_byteValue);
615 415044 : else if (apoColumnTypes[iCol] == MDB_Short)
616 0 : int_val = env->env->CallShortMethod(val, env->short_shortValue);
617 415044 : else if (apoColumnTypes[iCol] == MDB_Int)
618 415044 : int_val = env->env->CallIntMethod(val, env->integer_intValue);
619 415080 : if (env->ExceptionOccured()) return 0;
620 :
621 415080 : env->env->DeleteLocalRef(val);
622 :
623 415080 : return int_val;
624 : }
625 :
626 : /************************************************************************/
627 : /* GetColumnAsDouble() */
628 : /************************************************************************/
629 :
630 144 : double OGRMDBTable::GetColumnAsDouble(int iCol)
631 : {
632 144 : jobject val = GetColumnVal(iCol);
633 144 : if (!val) return 0;
634 :
635 144 : double double_val = 0;
636 144 : if (apoColumnTypes[iCol] == MDB_Double)
637 144 : double_val = env->env->CallDoubleMethod(val, env->double_doubleValue);
638 0 : else if (apoColumnTypes[iCol] == MDB_Float)
639 0 : double_val = env->env->CallFloatMethod(val, env->float_floatValue);
640 144 : if (env->ExceptionOccured()) return 0;
641 :
642 144 : env->env->DeleteLocalRef(val);
643 :
644 144 : return double_val;
645 : }
646 :
647 : /************************************************************************/
648 : /* GetColumnAsBinary() */
649 : /************************************************************************/
650 :
651 414936 : GByte* OGRMDBTable::GetColumnAsBinary(int iCol, int* pnBytes)
652 : {
653 414936 : *pnBytes = 0;
654 :
655 414936 : jobject val = GetColumnVal(iCol);
656 414936 : if (!val) return NULL;
657 :
658 414936 : if (!env->env->IsInstanceOf(val, env->byteArray_class))
659 0 : return NULL;
660 :
661 414936 : jbyteArray byteArray = (jbyteArray) val;
662 414936 : *pnBytes = env->env->GetArrayLength(byteArray);
663 414936 : if (env->ExceptionOccured()) return NULL;
664 : jboolean is_copy;
665 414936 : jbyte* elts = env->env->GetByteArrayElements(byteArray, &is_copy);
666 414936 : if (env->ExceptionOccured()) return NULL;
667 :
668 414936 : GByte* pData = (GByte*)CPLMalloc(*pnBytes);
669 414936 : memcpy(pData, elts, *pnBytes);
670 :
671 414936 : env->env->ReleaseByteArrayElements(byteArray, elts, JNI_ABORT);
672 :
673 414936 : env->env->DeleteLocalRef(val);
674 :
675 414936 : return pData;
676 : }
677 :
678 : /************************************************************************/
679 : /* DumpTable() */
680 : /************************************************************************/
681 :
682 0 : void OGRMDBTable::DumpTable()
683 : {
684 0 : ResetReading();
685 0 : int iRow = 0;
686 0 : int nCols = apoColumnNames.size();
687 0 : while(GetNextRow())
688 : {
689 0 : printf("Row = %d\n", iRow ++);
690 0 : for(int i=0;i<nCols;i++)
691 : {
692 0 : printf("%s = ", apoColumnNames[i].c_str());
693 0 : if (apoColumnTypes[i] == MDB_Float ||
694 : apoColumnTypes[i] == MDB_Double)
695 : {
696 0 : printf("%.15f\n", GetColumnAsDouble(i));
697 : }
698 0 : else if (apoColumnTypes[i] == MDB_Boolean ||
699 : apoColumnTypes[i] == MDB_Byte ||
700 : apoColumnTypes[i] == MDB_Short ||
701 : apoColumnTypes[i] == MDB_Int)
702 : {
703 0 : printf("%d\n", GetColumnAsInt(i));
704 : }
705 0 : else if (apoColumnTypes[i] == MDB_Binary ||
706 : apoColumnTypes[i] == MDB_OLE)
707 : {
708 : int nBytes;
709 0 : GByte* pData = GetColumnAsBinary(i, &nBytes);
710 0 : printf("(%d bytes)\n", nBytes);
711 0 : CPLFree(pData);
712 : }
713 : else
714 : {
715 0 : char* val = GetColumnAsString(i);
716 0 : printf("'%s'\n", val);
717 0 : CPLFree(val);
718 : }
719 : }
720 : }
721 0 : }
722 :
723 : /************************************************************************/
724 : /* GetColumnIndex() */
725 : /************************************************************************/
726 :
727 830088 : int OGRMDBTable::GetColumnIndex(const char* pszColName, int bEmitErrorIfNotFound)
728 : {
729 830088 : int nCols = apoColumnNames.size();
730 830088 : CPLString osColName(pszColName);
731 830664 : for(int i=0;i<nCols;i++)
732 : {
733 830664 : if (apoColumnNames[i] == osColName)
734 830088 : return i;
735 : }
736 0 : if (bEmitErrorIfNotFound)
737 0 : CPLError(CE_Failure, CPLE_AppDefined, "Cannot find column %s", pszColName);
738 0 : return -1;
739 : }
740 :
741 : /************************************************************************/
742 : /* GetRowCount() */
743 : /************************************************************************/
744 :
745 40 : int OGRMDBTable::GetRowCount()
746 : {
747 40 : if (env->bCalledFromJava)
748 0 : env->Init();
749 40 : int nRowCount = env->env->CallIntMethod(table, env->table_getRowCount);
750 40 : if (env->ExceptionOccured()) return 0;
751 40 : return nRowCount;
752 : }
|