1 /************************************************************************* 2 * 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * Copyright 2000, 2010 Oracle and/or its affiliates. 6 * 7 * OpenOffice.org - a multi-platform office productivity suite 8 * 9 * This file is part of OpenOffice.org. 10 * 11 * OpenOffice.org is free software: you can redistribute it and/or modify 12 * it under the terms of the GNU Lesser General Public License version 3 13 * only, as published by the Free Software Foundation. 14 * 15 * OpenOffice.org is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU Lesser General Public License version 3 for more details 19 * (a copy is included in the LICENSE file that accompanied this code). 20 * 21 * You should have received a copy of the GNU Lesser General Public License 22 * version 3 along with OpenOffice.org. If not, see 23 * <http://www.openoffice.org/license.html> 24 * for a copy of the LGPLv3 License. 25 * 26 ************************************************************************/ 27 28 // MARKER(update_precomp.py): autogen include statement, do not remove 29 #include "precompiled_connectivity.hxx" 30 #include "hsqldb/HStorageAccess.hxx" 31 #include <comphelper/processfactory.hxx> 32 #include <com/sun/star/embed/XStorage.hpp> 33 #include <com/sun/star/embed/ElementModes.hpp> 34 #include <com/sun/star/io/XStream.hpp> 35 #include "hsqldb/HStorageMap.hxx" 36 #include "hsqldb/StorageNativeInputStream.h" 37 #include "accesslog.hxx" 38 #include "diagnose_ex.h" 39 40 #include <string.h> 41 42 using namespace ::com::sun::star::container; 43 using namespace ::com::sun::star::uno; 44 using namespace ::com::sun::star::embed; 45 using namespace ::com::sun::star::io; 46 using namespace ::com::sun::star::lang; 47 using namespace ::connectivity::hsqldb; 48 49 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) ) 50 #define ThrowException(env, type, msg) { \ 51 env->ThrowNew(env->FindClass(type), msg); } 52 53 /* 54 * Class: com_sun_star_sdbcx_comp_hsqldb_NativeStorageAccess 55 * Method: openStream 56 * Signature: (Ljava/lang/String;Ljava/lang/String;I)V 57 */ 58 SAL_DLLPUBLIC_EXPORT void JNICALL Java_com_sun_star_sdbcx_comp_hsqldb_NativeStorageAccess_openStream 59 (JNIEnv * env, jobject /*obj_this*/,jstring name, jstring key, jint mode) 60 { 61 #ifdef HSQLDB_DBG 62 { 63 OperationLogFile( env, name, "data" ).logOperation( "openStream" ); 64 LogFile( env, name, "data" ).create(); 65 } 66 #endif 67 68 StorageContainer::registerStream(env,name,key,mode); 69 } 70 // ----------------------------------------------------------------------------- 71 /* 72 * Class: com_sun_star_sdbcx_comp_hsqldb_NativeStorageAccess 73 * Method: close 74 * Signature: (Ljava/lang/String;Ljava/lang/String;)V 75 */ 76 SAL_DLLPUBLIC_EXPORT void JNICALL Java_com_sun_star_sdbcx_comp_hsqldb_NativeStorageAccess_close 77 (JNIEnv * env, jobject /*obj_this*/,jstring name, jstring key) 78 { 79 #ifdef HSQLDB_DBG 80 { 81 ::rtl::OUString sKey = StorageContainer::jstring2ustring(env,key); 82 ::rtl::OUString sName = StorageContainer::jstring2ustring(env,name); 83 } 84 #endif 85 ::boost::shared_ptr<StreamHelper> pHelper = StorageContainer::getRegisteredStream(env,name,key); 86 Reference< XOutputStream> xFlush = pHelper.get() ? pHelper->getOutputStream() : Reference< XOutputStream>(); 87 if ( xFlush.is() ) 88 try 89 { 90 xFlush->flush(); 91 } 92 catch(Exception&) 93 { 94 OSL_ENSURE( false, "NativeStorageAccess::close: caught an exception while flushing!" ); 95 } 96 #ifdef HSQLDB_DBG 97 { 98 OperationLogFile aOpLog( env, name, "data" ); 99 aOpLog.logOperation( "close" ); 100 aOpLog.close(); 101 102 LogFile aDataLog( env, name, "data" ); 103 aDataLog.close(); 104 } 105 #endif 106 107 StorageContainer::revokeStream(env,name,key); 108 } 109 // ----------------------------------------------------------------------------- 110 /* 111 * Class: com_sun_star_sdbcx_comp_hsqldb_NativeStorageAccess 112 * Method: getFilePointer 113 * Signature: (Ljava/lang/String;Ljava/lang/String;)J 114 */ 115 SAL_DLLPUBLIC_EXPORT jlong JNICALL Java_com_sun_star_sdbcx_comp_hsqldb_NativeStorageAccess_getFilePointer 116 (JNIEnv * env, jobject /*obj_this*/,jstring name, jstring key) 117 { 118 #ifdef HSQLDB_DBG 119 OperationLogFile aOpLog( env, name, "data" ); 120 aOpLog.logOperation( "getFilePointer" ); 121 #endif 122 123 ::boost::shared_ptr<StreamHelper> pHelper = StorageContainer::getRegisteredStream(env,name,key); 124 OSL_ENSURE(pHelper.get(),"No stream helper!"); 125 126 jlong nReturn = pHelper.get() ? pHelper->getSeek()->getPosition() : jlong(0); 127 #ifdef HSQLDB_DBG 128 aOpLog.logReturn( nReturn ); 129 #endif 130 return nReturn; 131 } 132 // ----------------------------------------------------------------------------- 133 134 /* 135 * Class: com_sun_star_sdbcx_comp_hsqldb_NativeStorageAccess 136 * Method: length 137 * Signature: (Ljava/lang/String;Ljava/lang/String;)J 138 */ 139 SAL_DLLPUBLIC_EXPORT jlong JNICALL Java_com_sun_star_sdbcx_comp_hsqldb_NativeStorageAccess_length 140 (JNIEnv * env, jobject /*obj_this*/,jstring name, jstring key) 141 { 142 #ifdef HSQLDB_DBG 143 OperationLogFile aOpLog( env, name, "data" ); 144 aOpLog.logOperation( "length" ); 145 #endif 146 147 ::boost::shared_ptr<StreamHelper> pHelper = StorageContainer::getRegisteredStream(env,name,key); 148 OSL_ENSURE(pHelper.get(),"No stream helper!"); 149 150 jlong nReturn = pHelper.get() ? pHelper->getSeek()->getLength() :jlong(0); 151 #ifdef HSQLDB_DBG 152 aOpLog.logReturn( nReturn ); 153 #endif 154 return nReturn; 155 } 156 157 // ----------------------------------------------------------------------------- 158 159 jint read_from_storage_stream( JNIEnv * env, jobject /*obj_this*/, jstring name, jstring key, DataLogFile* logger ) 160 { 161 OSL_UNUSED( logger ); 162 ::boost::shared_ptr<StreamHelper> pHelper = StorageContainer::getRegisteredStream(env,name,key); 163 Reference< XInputStream> xIn = pHelper.get() ? pHelper->getInputStream() : Reference< XInputStream>(); 164 OSL_ENSURE(xIn.is(),"Input stream is NULL!"); 165 if ( xIn.is() ) 166 { 167 Sequence< ::sal_Int8 > aData(1); 168 sal_Int32 nBytesRead = -1; 169 try 170 { 171 nBytesRead = xIn->readBytes(aData,1); 172 } 173 catch(Exception& e) 174 { 175 StorageContainer::throwJavaException(e,env); 176 return -1; 177 178 } 179 if (nBytesRead <= 0) 180 { 181 return (-1); 182 } 183 else 184 { 185 sal_Int32 tmpInt = aData[0]; 186 if (tmpInt < 0 ) 187 tmpInt = 256 +tmpInt; 188 189 #ifdef HSQLDB_DBG 190 if ( logger ) 191 logger->write( tmpInt ); 192 #endif 193 return(tmpInt); 194 } 195 } 196 return -1; 197 } 198 199 // ----------------------------------------------------------------------------- 200 201 /* 202 * Class: com_sun_star_sdbcx_comp_hsqldb_NativeStorageAccess 203 * Method: read 204 * Signature: (Ljava/lang/String;Ljava/lang/String;)I 205 */ 206 SAL_DLLPUBLIC_EXPORT jint JNICALL Java_com_sun_star_sdbcx_comp_hsqldb_NativeStorageAccess_read__Ljava_lang_String_2Ljava_lang_String_2 207 (JNIEnv* env, jobject obj_this, jstring name, jstring key) 208 { 209 #ifdef HSQLDB_DBG 210 OperationLogFile aOpLog( env, name, "data" ); 211 aOpLog.logOperation( "read" ); 212 213 DataLogFile aDataLog( env, name, "data" ); 214 return read_from_storage_stream( env, obj_this, name, key, &aDataLog ); 215 #else 216 return read_from_storage_stream( env, obj_this, name, key ); 217 #endif 218 } 219 220 // ----------------------------------------------------------------------------- 221 222 jint read_from_storage_stream_into_buffer( JNIEnv * env, jobject /*obj_this*/,jstring name, jstring key, jbyteArray buffer, jint off, jint len, DataLogFile* logger ) 223 { 224 OSL_UNUSED( logger ); 225 #ifdef HSQLDB_DBG 226 { 227 ::rtl::OUString sKey = StorageContainer::jstring2ustring(env,key); 228 ::rtl::OUString sName = StorageContainer::jstring2ustring(env,name); 229 } 230 #endif 231 ::boost::shared_ptr<StreamHelper> pHelper = StorageContainer::getRegisteredStream(env,name,key); 232 Reference< XInputStream> xIn = pHelper.get() ? pHelper->getInputStream() : Reference< XInputStream>(); 233 OSL_ENSURE(xIn.is(),"Input stream is NULL!"); 234 if ( xIn.is() ) 235 { 236 jsize nLen = env->GetArrayLength(buffer); 237 if ( nLen < len || len <= 0 ) 238 { 239 ThrowException( env, 240 "java/io/IOException", 241 "len is greater or equal to the buffer size"); 242 return -1; 243 } 244 sal_Int32 nBytesRead = -1; 245 246 Sequence< ::sal_Int8 > aData(nLen); 247 try 248 { 249 nBytesRead = xIn->readBytes(aData, len); 250 } 251 catch(Exception& e) 252 { 253 StorageContainer::throwJavaException(e,env); 254 return -1; 255 } 256 257 if (nBytesRead <= 0) 258 return -1; 259 env->SetByteArrayRegion(buffer,off,nBytesRead,&aData[0]); 260 261 #ifdef HSQLDB_DBG 262 if ( logger ) 263 logger->write( aData.getConstArray(), nBytesRead ); 264 #endif 265 return nBytesRead; 266 } 267 ThrowException( env, 268 "java/io/IOException", 269 "Stream is not valid"); 270 return -1; 271 } 272 // ----------------------------------------------------------------------------- 273 274 /* 275 * Class: com_sun_star_sdbcx_comp_hsqldb_NativeStorageAccess 276 * Method: read 277 * Signature: (Ljava/lang/String;Ljava/lang/String;[BII)I 278 */ 279 SAL_DLLPUBLIC_EXPORT jint JNICALL Java_com_sun_star_sdbcx_comp_hsqldb_NativeStorageAccess_read__Ljava_lang_String_2Ljava_lang_String_2_3BII 280 (JNIEnv * env, jobject obj_this,jstring name, jstring key, jbyteArray buffer, jint off, jint len) 281 { 282 #ifdef HSQLDB_DBG 283 OperationLogFile aOpLog( env, name, "data" ); 284 aOpLog.logOperation( "read( byte[], int, int )" ); 285 286 DataLogFile aDataLog( env, name, "data" ); 287 return read_from_storage_stream_into_buffer( env, obj_this, name, key, buffer, off, len, &aDataLog ); 288 #else 289 return read_from_storage_stream_into_buffer( env, obj_this, name, key, buffer, off, len ); 290 #endif 291 } 292 293 // ----------------------------------------------------------------------------- 294 295 /* 296 * Class: com_sun_star_sdbcx_comp_hsqldb_NativeStorageAccess 297 * Method: readInt 298 * Signature: (Ljava/lang/String;Ljava/lang/String;)I 299 */ 300 SAL_DLLPUBLIC_EXPORT jint JNICALL Java_com_sun_star_sdbcx_comp_hsqldb_NativeStorageAccess_readInt 301 (JNIEnv * env, jobject /*obj_this*/,jstring name, jstring key) 302 { 303 #ifdef HSQLDB_DBG 304 OperationLogFile aOpLog( env, name, "data" ); 305 aOpLog.logOperation( "readInt" ); 306 #endif 307 308 ::boost::shared_ptr<StreamHelper> pHelper = StorageContainer::getRegisteredStream(env,name,key); 309 Reference< XInputStream> xIn = pHelper.get() ? pHelper->getInputStream() : Reference< XInputStream>(); 310 OSL_ENSURE(xIn.is(),"Input stream is NULL!"); 311 if ( xIn.is() ) 312 { 313 Sequence< ::sal_Int8 > aData(4); 314 sal_Int32 nBytesRead = -1; 315 try 316 { 317 nBytesRead = xIn->readBytes(aData, 4); 318 } 319 catch(Exception& e) 320 { 321 StorageContainer::throwJavaException(e,env); 322 return -1; 323 } 324 325 if ( nBytesRead != 4 ) { 326 ThrowException( env, 327 "java/io/IOException", 328 "Bytes read != 4"); 329 return -1; 330 } 331 332 Sequence< sal_Int32 > ch(4); 333 for(sal_Int32 i = 0;i < 4; ++i) 334 { 335 ch[i] = aData[i]; 336 if (ch[i] < 0 ) 337 ch[i] = 256 + ch[i]; 338 } 339 340 if ((ch[0] | ch[1] | ch[2] | ch[3]) < 0) 341 { 342 ThrowException( env, 343 "java/io/IOException", 344 "One byte is < 0"); 345 return -1; 346 } 347 jint nRet = ((ch[0] << 24) + (ch[1] << 16) + (ch[2] << 8) + (ch[3] << 0)); 348 #ifdef HSQLDB_DBG 349 DataLogFile aDataLog( env, name, "data" ); 350 aDataLog.write( nRet ); 351 352 aOpLog.logReturn( nRet ); 353 #endif 354 return nRet; 355 } 356 ThrowException( env, 357 "java/io/IOException", 358 "No InputStream"); 359 return -1; 360 } 361 // ----------------------------------------------------------------------------- 362 363 /* 364 * Class: com_sun_star_sdbcx_comp_hsqldb_NativeStorageAccess 365 * Method: seek 366 * Signature: (Ljava/lang/String;Ljava/lang/String;J)V 367 */ 368 SAL_DLLPUBLIC_EXPORT void JNICALL Java_com_sun_star_sdbcx_comp_hsqldb_NativeStorageAccess_seek 369 (JNIEnv * env, jobject /*obj_this*/,jstring name, jstring key, jlong position) 370 { 371 #ifdef HSQLDB_DBG 372 OperationLogFile aOpLog( env, name, "data" ); 373 aOpLog.logOperation( "seek", position ); 374 #endif 375 376 ::boost::shared_ptr<StreamHelper> pHelper = StorageContainer::getRegisteredStream(env,name,key); 377 Reference< XSeekable> xSeek = pHelper.get() ? pHelper->getSeek() : Reference< XSeekable>(); 378 379 OSL_ENSURE(xSeek.is(),"No Seekable stream!"); 380 if ( xSeek.is() ) 381 { 382 #ifdef HSQLDB_DBG 383 DataLogFile aDataLog( env, name, "data" ); 384 #endif 385 386 ::sal_Int64 nLen = xSeek->getLength(); 387 if ( nLen < position) 388 { 389 static ::sal_Int64 BUFFER_SIZE = 9192; 390 #ifdef HSQLDB_DBG 391 aDataLog.seek( nLen ); 392 #endif 393 xSeek->seek(nLen); 394 Reference< XOutputStream> xOut = pHelper->getOutputStream(); 395 OSL_ENSURE(xOut.is(),"No output stream!"); 396 397 ::sal_Int64 diff = position - nLen; 398 sal_Int32 n; 399 while( diff != 0 ) 400 { 401 if ( BUFFER_SIZE < diff ) 402 { 403 n = static_cast<sal_Int32>(BUFFER_SIZE); 404 diff = diff - BUFFER_SIZE; 405 } 406 else 407 { 408 n = static_cast<sal_Int32>(diff); 409 diff = 0; 410 } 411 Sequence< ::sal_Int8 > aData(n); 412 memset(aData.getArray(),0,n); 413 xOut->writeBytes(aData); 414 #ifdef HSQLDB_DBG 415 aDataLog.write( aData.getConstArray(), n ); 416 #endif 417 } 418 } 419 xSeek->seek(position); 420 OSL_ENSURE(xSeek->getPosition() == position,"Wrong position after seeking the stream"); 421 422 #ifdef HSQLDB_DBG 423 aDataLog.seek( position ); 424 OSL_ENSURE( xSeek->getPosition() == aDataLog.tell(), "Wrong position after seeking the stream" ); 425 #endif 426 } 427 } 428 // ----------------------------------------------------------------------------- 429 430 void write_to_storage_stream_from_buffer( JNIEnv* env, jobject /*obj_this*/, jstring name, jstring key, jbyteArray buffer, jint off, jint len, DataLogFile* logger ) 431 { 432 OSL_UNUSED( logger ); 433 ::boost::shared_ptr<StreamHelper> pHelper = StorageContainer::getRegisteredStream(env,name,key); 434 Reference< XOutputStream> xOut = pHelper.get() ? pHelper->getOutputStream() : Reference< XOutputStream>(); 435 OSL_ENSURE(xOut.is(),"Stream is NULL"); 436 437 try 438 { 439 if ( xOut.is() ) 440 { 441 jbyte *buf = env->GetByteArrayElements(buffer,NULL); 442 if (JNI_FALSE != env->ExceptionCheck()) 443 { 444 env->ExceptionClear(); 445 OSL_ENSURE(0,"ExceptionClear"); 446 } 447 OSL_ENSURE(buf,"buf is NULL"); 448 if ( buf && len > 0 && len <= env->GetArrayLength(buffer)) 449 { 450 Sequence< ::sal_Int8 > aData(buf + off,len); 451 env->ReleaseByteArrayElements(buffer, buf, JNI_ABORT); 452 xOut->writeBytes(aData); 453 #ifdef HSQLDB_DBG 454 if ( logger ) 455 logger->write( aData.getConstArray(), len ); 456 #endif 457 } 458 } 459 else 460 { 461 ThrowException( env, 462 "java/io/IOException", 463 "No OutputStream"); 464 } 465 } 466 catch(Exception& e) 467 { 468 OSL_ENSURE(0,"Exception caught! : write [BII)V"); 469 StorageContainer::throwJavaException(e,env); 470 } 471 } 472 473 // ----------------------------------------------------------------------------- 474 475 /* 476 * Class: com_sun_star_sdbcx_comp_hsqldb_NativeStorageAccess 477 * Method: write 478 * Signature: (Ljava/lang/String;Ljava/lang/String;[BII)V 479 */ 480 SAL_DLLPUBLIC_EXPORT void JNICALL Java_com_sun_star_sdbcx_comp_hsqldb_NativeStorageAccess_write 481 (JNIEnv * env, jobject obj_this,jstring name, jstring key, jbyteArray buffer, jint off, jint len) 482 { 483 #ifdef HSQLDB_DBG 484 OperationLogFile aOpLog( env, name, "data" ); 485 aOpLog.logOperation( "write( byte[], int, int )" ); 486 487 DataLogFile aDataLog( env, name, "data" ); 488 write_to_storage_stream_from_buffer( env, obj_this, name, key, buffer, off, len, &aDataLog ); 489 #else 490 write_to_storage_stream_from_buffer( env, obj_this, name, key, buffer, off, len ); 491 #endif 492 } 493 // ----------------------------------------------------------------------------- 494 495 void write_to_storage_stream( JNIEnv* env, jobject /*obj_this*/, jstring name, jstring key, jint v, DataLogFile* logger ) 496 { 497 OSL_UNUSED( logger ); 498 499 ::boost::shared_ptr<StreamHelper> pHelper = StorageContainer::getRegisteredStream(env,name,key); 500 Reference< XOutputStream> xOut = pHelper.get() ? pHelper->getOutputStream() : Reference< XOutputStream>(); 501 OSL_ENSURE(xOut.is(),"Stream is NULL"); 502 try 503 { 504 if ( xOut.is() ) 505 { 506 Sequence< ::sal_Int8 > oneByte(4); 507 oneByte[0] = (sal_Int8) ((v >> 24) & 0xFF); 508 oneByte[1] = (sal_Int8) ((v >> 16) & 0xFF); 509 oneByte[2] = (sal_Int8) ((v >> 8) & 0xFF); 510 oneByte[3] = (sal_Int8) ((v >> 0) & 0xFF); 511 512 xOut->writeBytes(oneByte); 513 #ifdef HSQLDB_DBG 514 if ( logger ) 515 logger->write( oneByte.getConstArray(), 4 ); 516 #endif 517 } 518 else 519 { 520 ThrowException( env, 521 "java/io/IOException", 522 "No OutputStream"); 523 } 524 } 525 catch(Exception& e) 526 { 527 OSL_ENSURE(0,"Exception catched! : writeBytes(aData);"); 528 StorageContainer::throwJavaException(e,env); 529 } 530 } 531 532 // ----------------------------------------------------------------------------- 533 534 /* 535 * Class: com_sun_star_sdbcx_comp_hsqldb_NativeStorageAccess 536 * Method: writeInt 537 * Signature: (Ljava/lang/String;Ljava/lang/String;I)V 538 */ 539 SAL_DLLPUBLIC_EXPORT void JNICALL Java_com_sun_star_sdbcx_comp_hsqldb_NativeStorageAccess_writeInt 540 (JNIEnv * env, jobject obj_this,jstring name, jstring key, jint v) 541 { 542 #ifdef HSQLDB_DBG 543 OperationLogFile aOpLog( env, name, "data" ); 544 aOpLog.logOperation( "writeInt" ); 545 546 DataLogFile aDataLog( env, name, "data" ); 547 write_to_storage_stream( env, obj_this, name, key, v, &aDataLog ); 548 #else 549 write_to_storage_stream( env, obj_this, name, key, v ); 550 #endif 551 } 552