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 6 : OGRMDBJavaEnv::OGRMDBJavaEnv()
42 : {
43 6 : jvm = NULL;
44 6 : env = NULL;
45 6 : bCalledFromJava = FALSE;
46 :
47 6 : byteArray_class = NULL;
48 :
49 6 : file_class = NULL;
50 6 : file_constructor = NULL;
51 6 : database_class = NULL;
52 6 : database_open = NULL;
53 6 : database_close = NULL;
54 6 : database_getTableNames = NULL;
55 6 : database_getTable = NULL;
56 :
57 6 : table_class = NULL;
58 6 : table_getColumns = NULL;
59 6 : table_iterator = NULL;
60 6 : table_getRowCount = NULL;
61 :
62 6 : column_class = NULL;
63 6 : column_getName = NULL;
64 6 : column_getType = NULL;
65 6 : column_getLength = NULL;
66 6 : column_isVariableLength = NULL;
67 :
68 6 : datatype_class = NULL;
69 6 : datatype_getValue = NULL;
70 :
71 6 : list_class = NULL;
72 6 : list_iterator = NULL;
73 :
74 6 : set_class = NULL;
75 6 : set_iterator = NULL;
76 :
77 6 : map_class = NULL;
78 6 : map_get = NULL;
79 :
80 6 : iterator_class = NULL;
81 6 : iterator_hasNext = NULL;
82 6 : iterator_next = NULL;
83 :
84 6 : object_class = NULL;
85 6 : object_toString = NULL;
86 6 : object_getClass = NULL;
87 :
88 6 : boolean_class = NULL;
89 6 : boolean_booleanValue = NULL;
90 :
91 6 : byte_class = NULL;
92 6 : byte_byteValue = NULL;
93 :
94 6 : short_class = NULL;
95 6 : short_shortValue = NULL;
96 :
97 6 : integer_class = NULL;
98 6 : integer_intValue = NULL;
99 :
100 6 : float_class = NULL;
101 6 : float_floatValue = NULL;
102 :
103 6 : double_class = NULL;
104 6 : double_doubleValue = NULL;
105 6 : }
106 :
107 : /************************************************************************/
108 : /* ~OGRMDBJavaEnv() */
109 : /************************************************************************/
110 :
111 6 : OGRMDBJavaEnv::~OGRMDBJavaEnv()
112 : {
113 6 : if (jvm)
114 : {
115 6 : env->DeleteLocalRef(byteArray_class);
116 :
117 6 : env->DeleteLocalRef(file_class);
118 6 : env->DeleteLocalRef(database_class);
119 :
120 6 : env->DeleteLocalRef(table_class);
121 :
122 6 : env->DeleteLocalRef(column_class);
123 :
124 6 : env->DeleteLocalRef(datatype_class);
125 :
126 6 : env->DeleteLocalRef(list_class);
127 :
128 6 : env->DeleteLocalRef(set_class);
129 :
130 6 : env->DeleteLocalRef(map_class);
131 :
132 6 : env->DeleteLocalRef(iterator_class);
133 :
134 6 : env->DeleteLocalRef(object_class);
135 :
136 6 : env->DeleteLocalRef(boolean_class);
137 6 : env->DeleteLocalRef(byte_class);
138 6 : env->DeleteLocalRef(short_class);
139 6 : env->DeleteLocalRef(integer_class);
140 6 : env->DeleteLocalRef(float_class);
141 6 : 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 6 : }
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 6 : int OGRMDBJavaEnv::Init()
159 : {
160 6 : if (jvm_static == NULL)
161 : {
162 : JavaVM* vmBuf[1];
163 : jsize nVMs;
164 :
165 : /* Are we already called from Java ? */
166 3 : 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 3 : args.version = JNI_VERSION_1_2;
184 3 : const char* pszClassPath = CPLGetConfigOption("CLASSPATH", NULL);
185 3 : CPLString osClassPathOption;
186 3 : if (pszClassPath)
187 : {
188 3 : args.nOptions = 1;
189 3 : osClassPathOption.Printf("-Djava.class.path=%s", pszClassPath);
190 3 : options[0].optionString = (char*) osClassPathOption.c_str();
191 3 : args.options = options;
192 : }
193 : else
194 0 : args.nOptions = 0;
195 3 : args.ignoreUnrecognized = JNI_FALSE;
196 :
197 3 : int ret = JNI_CreateJavaVM(&jvm, (void **)&env, &args);
198 3 : 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 3 : jvm_static = jvm;
205 3 : env_static = env;
206 : }
207 : }
208 : else
209 : {
210 3 : jvm = jvm_static;
211 3 : env = env_static;
212 : }
213 :
214 6 : CHECK(byteArray_class, env->FindClass("[B"));
215 6 : CHECK(file_class, env->FindClass("java/io/File"));
216 6 : CHECK(file_constructor, env->GetMethodID(file_class, "<init>", "(Ljava/lang/String;)V"));
217 6 : CHECK(database_class, env->FindClass("com/healthmarketscience/jackcess/Database"));
218 :
219 6 : CHECK(database_open, env->GetStaticMethodID(database_class, "open", "(Ljava/io/File;Z)Lcom/healthmarketscience/jackcess/Database;"));
220 6 : CHECK(database_close, env->GetMethodID(database_class, "close", "()V"));
221 6 : CHECK(database_getTableNames, env->GetMethodID(database_class, "getTableNames", "()Ljava/util/Set;"));
222 6 : CHECK(database_getTable, env->GetMethodID(database_class, "getTable", "(Ljava/lang/String;)Lcom/healthmarketscience/jackcess/Table;"));
223 :
224 6 : CHECK(table_class, env->FindClass("com/healthmarketscience/jackcess/Table"));
225 6 : CHECK(table_getColumns, env->GetMethodID(table_class, "getColumns", "()Ljava/util/List;"));
226 6 : CHECK(table_iterator, env->GetMethodID(table_class, "iterator", "()Ljava/util/Iterator;"));
227 6 : CHECK(table_getRowCount, env->GetMethodID(table_class, "getRowCount", "()I"));
228 :
229 6 : CHECK(column_class, env->FindClass("com/healthmarketscience/jackcess/Column"));
230 6 : CHECK(column_getName, env->GetMethodID(column_class, "getName", "()Ljava/lang/String;"));
231 6 : CHECK(column_getType, env->GetMethodID(column_class, "getType", "()Lcom/healthmarketscience/jackcess/DataType;"));
232 6 : CHECK(column_getLength, env->GetMethodID(column_class, "getLength", "()S"));
233 6 : CHECK(column_isVariableLength, env->GetMethodID(column_class, "isVariableLength", "()Z"));
234 :
235 6 : CHECK(datatype_class, env->FindClass("com/healthmarketscience/jackcess/DataType"));
236 6 : CHECK(datatype_getValue, env->GetMethodID(datatype_class, "getValue", "()B"));
237 :
238 6 : CHECK(list_class, env->FindClass("java/util/List"));
239 6 : CHECK(list_iterator, env->GetMethodID(list_class, "iterator", "()Ljava/util/Iterator;"));
240 :
241 6 : CHECK(set_class, env->FindClass("java/util/Set"));
242 6 : CHECK(set_iterator, env->GetMethodID(set_class, "iterator", "()Ljava/util/Iterator;"));
243 :
244 6 : CHECK(map_class, env->FindClass("java/util/Map"));
245 6 : CHECK(map_get, env->GetMethodID(map_class, "get", "(Ljava/lang/Object;)Ljava/lang/Object;"));
246 :
247 6 : CHECK(iterator_class, env->FindClass("java/util/Iterator"));
248 6 : CHECK(iterator_hasNext, env->GetMethodID(iterator_class, "hasNext", "()Z"));
249 6 : CHECK(iterator_next, env->GetMethodID(iterator_class, "next", "()Ljava/lang/Object;"));
250 :
251 6 : CHECK(object_class, env->FindClass("java/lang/Object"));
252 6 : CHECK(object_toString, env->GetMethodID(object_class, "toString", "()Ljava/lang/String;"));
253 6 : CHECK(object_getClass, env->GetMethodID(object_class, "getClass", "()Ljava/lang/Class;"));
254 :
255 6 : CHECK(boolean_class, env->FindClass("java/lang/Boolean"));
256 6 : CHECK(boolean_booleanValue, env->GetMethodID(boolean_class, "booleanValue", "()Z"));
257 :
258 6 : CHECK(byte_class, env->FindClass("java/lang/Byte"));
259 6 : CHECK(byte_byteValue, env->GetMethodID(byte_class, "byteValue", "()B"));
260 :
261 6 : CHECK(short_class, env->FindClass("java/lang/Short"));
262 6 : CHECK(short_shortValue, env->GetMethodID(short_class, "shortValue", "()S"));
263 :
264 6 : CHECK(integer_class, env->FindClass("java/lang/Integer"));
265 6 : CHECK(integer_intValue, env->GetMethodID(integer_class, "intValue", "()I"));
266 :
267 6 : CHECK(float_class, env->FindClass("java/lang/Float"));
268 6 : CHECK(float_floatValue, env->GetMethodID(float_class, "floatValue", "()F"));
269 :
270 6 : CHECK(double_class, env->FindClass("java/lang/Double"));
271 6 : CHECK(double_doubleValue, env->GetMethodID(integer_class, "doubleValue", "()D"));
272 :
273 6 : return TRUE;
274 : }
275 :
276 :
277 : /************************************************************************/
278 : /* ExceptionOccured() */
279 : /************************************************************************/
280 :
281 5199898 : int OGRMDBJavaEnv::ExceptionOccured()
282 : {
283 5199898 : jthrowable exc = env->ExceptionOccurred();
284 5199898 : if (exc)
285 : {
286 0 : env->ExceptionDescribe();
287 0 : env->ExceptionClear();
288 0 : return TRUE;
289 : }
290 5199898 : return FALSE;
291 : }
292 :
293 :
294 : /************************************************************************/
295 : /* OGRMDBDatabase() */
296 : /************************************************************************/
297 :
298 6 : OGRMDBDatabase::OGRMDBDatabase()
299 : {
300 6 : env = NULL;
301 6 : database = NULL;
302 6 : }
303 :
304 : /************************************************************************/
305 : /* ~OGRMDBDatabase() */
306 : /************************************************************************/
307 :
308 6 : OGRMDBDatabase::~OGRMDBDatabase()
309 : {
310 6 : if (database)
311 : {
312 6 : CPLDebug("MDB", "Closing database");
313 6 : env->env->CallVoidMethod(database, env->database_close);
314 :
315 6 : env->env->DeleteGlobalRef(database);
316 : }
317 6 : }
318 :
319 : /************************************************************************/
320 : /* Open() */
321 : /************************************************************************/
322 :
323 6 : OGRMDBDatabase* OGRMDBDatabase::Open(OGRMDBJavaEnv* env, const char* pszName)
324 : {
325 6 : jstring jstr = env->env->NewStringUTF(pszName);
326 6 : jobject file = env->env->NewObject(env->file_class, env->file_constructor, jstr);
327 6 : if (env->ExceptionOccured()) return NULL;
328 6 : env->env->ReleaseStringUTFChars(jstr, NULL);
329 :
330 6 : jobject database = env->env->CallStaticObjectMethod(env->database_class, env->database_open, file, JNI_TRUE);
331 :
332 6 : env->env->DeleteLocalRef(file);
333 :
334 6 : if (env->ExceptionOccured()) return NULL;
335 6 : if (database == NULL)
336 0 : return NULL;
337 :
338 6 : OGRMDBDatabase* poDB = new OGRMDBDatabase();
339 6 : poDB->env = env;
340 6 : poDB->database = env->env->NewGlobalRef(database);
341 6 : env->env->DeleteLocalRef(database);
342 6 : return poDB;
343 : }
344 :
345 : /************************************************************************/
346 : /* FetchTableNames() */
347 : /************************************************************************/
348 :
349 6 : int OGRMDBDatabase::FetchTableNames()
350 : {
351 6 : if (env->bCalledFromJava)
352 0 : env->Init();
353 :
354 6 : jobject table_set = env->env->CallObjectMethod(database, env->database_getTableNames);
355 6 : if (env->ExceptionOccured()) return FALSE;
356 6 : jobject iterator = env->env->CallObjectMethod(table_set, env->set_iterator);
357 6 : if (env->ExceptionOccured()) return FALSE;
358 :
359 240 : while( env->env->CallBooleanMethod(iterator, env->iterator_hasNext) )
360 : {
361 228 : if (env->ExceptionOccured()) return FALSE;
362 228 : jstring table_name_jstring = (jstring) env->env->CallObjectMethod(iterator, env->iterator_next);
363 228 : if (env->ExceptionOccured()) return FALSE;
364 : jboolean is_copy;
365 228 : const char* table_name_str = env->env->GetStringUTFChars(table_name_jstring, &is_copy);
366 :
367 228 : apoTableNames.push_back(table_name_str);
368 : //CPLDebug("MDB", "Table %s", table_name_str);
369 :
370 228 : env->env->ReleaseStringUTFChars(table_name_jstring, table_name_str);
371 228 : env->env->DeleteLocalRef(table_name_jstring);
372 : }
373 6 : env->env->DeleteLocalRef(iterator);
374 6 : env->env->DeleteLocalRef(table_set);
375 6 : return TRUE;
376 : }
377 :
378 : /************************************************************************/
379 : /* GetTable() */
380 : /************************************************************************/
381 :
382 44 : OGRMDBTable* OGRMDBDatabase::GetTable(const char* pszTableName)
383 : {
384 44 : if (env->bCalledFromJava)
385 0 : env->Init();
386 :
387 44 : jstring table_name_jstring = env->env->NewStringUTF(pszTableName);
388 44 : jobject table = env->env->CallObjectMethod(database, env->database_getTable, table_name_jstring);
389 44 : if (env->ExceptionOccured()) return NULL;
390 44 : env->env->DeleteLocalRef(table_name_jstring);
391 :
392 44 : if (!table)
393 2 : return NULL;
394 :
395 42 : jobject global_table = env->env->NewGlobalRef(table);
396 42 : env->env->DeleteLocalRef(table);
397 42 : table = global_table;
398 :
399 42 : OGRMDBTable* poTable = new OGRMDBTable(env, this, table, pszTableName);
400 42 : if (!poTable->FetchColumns())
401 : {
402 0 : delete poTable;
403 0 : return NULL;
404 : }
405 42 : return poTable;
406 : }
407 :
408 : /************************************************************************/
409 : /* OGRMDBTable() */
410 : /************************************************************************/
411 :
412 42 : OGRMDBTable::OGRMDBTable(OGRMDBJavaEnv* env, OGRMDBDatabase* poDB, jobject table, const char* pszTableName )
413 : {
414 42 : this->env = env;
415 42 : this->poDB = poDB;
416 42 : this->table = table;
417 42 : osTableName = pszTableName;
418 42 : table_iterator_obj = NULL;
419 42 : row = NULL;
420 42 : }
421 :
422 : /************************************************************************/
423 : /* ~OGRMDBTable() */
424 : /************************************************************************/
425 :
426 42 : OGRMDBTable::~OGRMDBTable()
427 : {
428 42 : if (env)
429 : {
430 : //CPLDebug("MDB", "Freeing table %s", osTableName.c_str());
431 42 : if (env->bCalledFromJava)
432 0 : env->Init();
433 :
434 : int i;
435 498 : for(i=0;i<(int)apoColumnNameObjects.size();i++)
436 456 : env->env->DeleteGlobalRef(apoColumnNameObjects[i]);
437 :
438 42 : env->env->DeleteGlobalRef(table_iterator_obj);
439 42 : env->env->DeleteGlobalRef(row);
440 42 : env->env->DeleteGlobalRef(table);
441 : }
442 42 : }
443 :
444 : /************************************************************************/
445 : /* FetchColumns() */
446 : /************************************************************************/
447 :
448 42 : int OGRMDBTable::FetchColumns()
449 : {
450 42 : if (env->bCalledFromJava)
451 0 : env->Init();
452 :
453 42 : jobject column_lists = env->env->CallObjectMethod(table, env->table_getColumns);
454 42 : if (env->ExceptionOccured()) return FALSE;
455 :
456 42 : jobject iterator_cols = env->env->CallObjectMethod(column_lists, env->list_iterator);
457 42 : if (env->ExceptionOccured()) return FALSE;
458 :
459 540 : while( env->env->CallBooleanMethod(iterator_cols, env->iterator_hasNext) )
460 : {
461 456 : if (env->ExceptionOccured()) return FALSE;
462 :
463 456 : jobject column = env->env->CallObjectMethod(iterator_cols, env->iterator_next);
464 456 : if (env->ExceptionOccured()) return FALSE;
465 :
466 456 : jstring column_name_jstring = (jstring) env->env->CallObjectMethod(column, env->column_getName);
467 456 : if (env->ExceptionOccured()) return FALSE;
468 : jboolean is_copy;
469 456 : const char* column_name_str = env->env->GetStringUTFChars(column_name_jstring, &is_copy);
470 456 : apoColumnNames.push_back(column_name_str);
471 456 : env->env->ReleaseStringUTFChars(column_name_jstring, column_name_str);
472 :
473 456 : apoColumnNameObjects.push_back((jstring) env->env->NewGlobalRef(column_name_jstring));
474 456 : env->env->DeleteLocalRef(column_name_jstring);
475 :
476 456 : jobject column_type = env->env->CallObjectMethod(column, env->column_getType);
477 456 : if (env->ExceptionOccured()) return FALSE;
478 456 : int type = env->env->CallByteMethod(column_type, env->datatype_getValue);
479 456 : if (env->ExceptionOccured()) return FALSE;
480 456 : apoColumnTypes.push_back(type);
481 :
482 456 : int isvariablelength = env->env->CallBooleanMethod(column, env->column_isVariableLength);
483 456 : if (env->ExceptionOccured()) return FALSE;
484 456 : if (!isvariablelength)
485 : {
486 360 : int length = env->env->CallShortMethod(column, env->column_getLength);
487 360 : if (env->ExceptionOccured()) return FALSE;
488 360 : apoColumnLengths.push_back(length);
489 : }
490 : else
491 96 : apoColumnLengths.push_back(0);
492 :
493 : //CPLDebug("MDB", "Column %s, type = %d", apoColumnNames[apoColumnNames.size()-1].c_str(), type);
494 :
495 456 : env->env->DeleteLocalRef(column_type);
496 :
497 456 : env->env->DeleteLocalRef(column);
498 : }
499 42 : env->env->DeleteLocalRef(iterator_cols);
500 42 : env->env->DeleteLocalRef(column_lists);
501 :
502 42 : return TRUE;
503 : }
504 :
505 : /************************************************************************/
506 : /* ResetReading() */
507 : /************************************************************************/
508 :
509 145 : void OGRMDBTable::ResetReading()
510 : {
511 145 : if (env->bCalledFromJava)
512 0 : env->Init();
513 :
514 145 : env->env->DeleteGlobalRef(table_iterator_obj);
515 145 : table_iterator_obj = NULL;
516 145 : env->env->DeleteGlobalRef(row);
517 145 : row = NULL;
518 145 : }
519 :
520 : /************************************************************************/
521 : /* GetNextRow() */
522 : /************************************************************************/
523 :
524 273598 : int OGRMDBTable::GetNextRow()
525 : {
526 273598 : if (env->bCalledFromJava)
527 0 : env->Init();
528 :
529 273598 : if (table_iterator_obj == NULL)
530 : {
531 104 : table_iterator_obj = env->env->CallObjectMethod(table, env->table_iterator);
532 104 : if (env->ExceptionOccured()) return FALSE;
533 104 : if (table_iterator_obj)
534 : {
535 104 : jobject global_table_iterator_obj = env->env->NewGlobalRef(table_iterator_obj);
536 104 : env->env->DeleteLocalRef(table_iterator_obj);
537 104 : table_iterator_obj = global_table_iterator_obj;
538 : }
539 : }
540 273598 : if (table_iterator_obj == NULL)
541 0 : return FALSE;
542 :
543 273598 : if (!env->env->CallBooleanMethod(table_iterator_obj, env->iterator_hasNext))
544 60 : return FALSE;
545 273538 : if (env->ExceptionOccured()) return FALSE;
546 :
547 273538 : if (row)
548 : {
549 273434 : env->env->DeleteGlobalRef(row);
550 273434 : row = NULL;
551 : }
552 :
553 273538 : row = env->env->CallObjectMethod(table_iterator_obj, env->iterator_next);
554 273538 : if (env->ExceptionOccured()) return FALSE;
555 273538 : if (row == NULL)
556 0 : return FALSE;
557 :
558 273538 : jobject global_row = env->env->NewGlobalRef(row);
559 273538 : env->env->DeleteLocalRef(row);
560 273538 : row = global_row;
561 :
562 273538 : return TRUE;
563 : }
564 :
565 : /************************************************************************/
566 : /* GetColumnVal() */
567 : /************************************************************************/
568 :
569 2187746 : jobject OGRMDBTable::GetColumnVal(int iCol)
570 : {
571 2187746 : if (row == NULL)
572 0 : return NULL;
573 :
574 2187746 : jobject val = env->env->CallObjectMethod(row, env->map_get, apoColumnNameObjects[iCol]);
575 2187746 : if (env->ExceptionOccured()) return NULL;
576 2187746 : return val;
577 : }
578 :
579 : /************************************************************************/
580 : /* GetColumnAsString() */
581 : /************************************************************************/
582 :
583 1640598 : char* OGRMDBTable::GetColumnAsString(int iCol)
584 : {
585 1640598 : jobject val = GetColumnVal(iCol);
586 1640598 : if (!val) return NULL;
587 :
588 1640598 : jstring val_jstring = (jstring) env->env->CallObjectMethod(val, env->object_toString);
589 1640598 : if (env->ExceptionOccured()) return NULL;
590 : jboolean is_copy;
591 1640598 : const char* val_str = env->env->GetStringUTFChars(val_jstring, &is_copy);
592 1640598 : char* dup_str = (val_str) ? CPLStrdup(val_str) : NULL;
593 1640598 : env->env->ReleaseStringUTFChars(val_jstring, val_str);
594 1640598 : env->env->DeleteLocalRef(val_jstring);
595 :
596 1640598 : env->env->DeleteLocalRef(val);
597 :
598 1640598 : return dup_str;
599 : }
600 :
601 : /************************************************************************/
602 : /* GetColumnAsInt() */
603 : /************************************************************************/
604 :
605 273574 : int OGRMDBTable::GetColumnAsInt(int iCol)
606 : {
607 273574 : jobject val = GetColumnVal(iCol);
608 273574 : if (!val) return 0;
609 :
610 273574 : int int_val = 0;
611 273574 : if (apoColumnTypes[iCol] == MDB_Boolean)
612 18 : int_val = env->env->CallBooleanMethod(val, env->boolean_booleanValue);
613 273556 : else if (apoColumnTypes[iCol] == MDB_Byte)
614 0 : int_val = env->env->CallByteMethod(val, env->byte_byteValue);
615 273556 : else if (apoColumnTypes[iCol] == MDB_Short)
616 0 : int_val = env->env->CallShortMethod(val, env->short_shortValue);
617 273556 : else if (apoColumnTypes[iCol] == MDB_Int)
618 273556 : int_val = env->env->CallIntMethod(val, env->integer_intValue);
619 273574 : if (env->ExceptionOccured()) return 0;
620 :
621 273574 : env->env->DeleteLocalRef(val);
622 :
623 273574 : return int_val;
624 : }
625 :
626 : /************************************************************************/
627 : /* GetColumnAsDouble() */
628 : /************************************************************************/
629 :
630 72 : double OGRMDBTable::GetColumnAsDouble(int iCol)
631 : {
632 72 : jobject val = GetColumnVal(iCol);
633 72 : if (!val) return 0;
634 :
635 72 : double double_val = 0;
636 72 : if (apoColumnTypes[iCol] == MDB_Double)
637 72 : 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 72 : if (env->ExceptionOccured()) return 0;
641 :
642 72 : env->env->DeleteLocalRef(val);
643 :
644 72 : return double_val;
645 : }
646 :
647 : /************************************************************************/
648 : /* GetColumnAsBinary() */
649 : /************************************************************************/
650 :
651 273502 : GByte* OGRMDBTable::GetColumnAsBinary(int iCol, int* pnBytes)
652 : {
653 273502 : *pnBytes = 0;
654 :
655 273502 : jobject val = GetColumnVal(iCol);
656 273502 : if (!val) return NULL;
657 :
658 273502 : if (!env->env->IsInstanceOf(val, env->byteArray_class))
659 0 : return NULL;
660 :
661 273502 : jbyteArray byteArray = (jbyteArray) val;
662 273502 : *pnBytes = env->env->GetArrayLength(byteArray);
663 273502 : if (env->ExceptionOccured()) return NULL;
664 : jboolean is_copy;
665 273502 : jbyte* elts = env->env->GetByteArrayElements(byteArray, &is_copy);
666 273502 : if (env->ExceptionOccured()) return NULL;
667 :
668 273502 : GByte* pData = (GByte*)CPLMalloc(*pnBytes);
669 273502 : memcpy(pData, elts, *pnBytes);
670 :
671 273502 : env->env->ReleaseByteArrayElements(byteArray, elts, JNI_ABORT);
672 :
673 273502 : env->env->DeleteLocalRef(val);
674 :
675 273502 : 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 547112 : int OGRMDBTable::GetColumnIndex(const char* pszColName, int bEmitErrorIfNotFound)
728 : {
729 547112 : int nCols = apoColumnNames.size();
730 547112 : CPLString osColName(pszColName);
731 547400 : for(int i=0;i<nCols;i++)
732 : {
733 547400 : if (apoColumnNames[i] == osColName)
734 547112 : 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 20 : int OGRMDBTable::GetRowCount()
746 : {
747 20 : if (env->bCalledFromJava)
748 0 : env->Init();
749 20 : int nRowCount = env->env->CallIntMethod(table, env->table_getRowCount);
750 20 : if (env->ExceptionOccured()) return 0;
751 20 : return nRowCount;
752 : }
|