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