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 
31 #if defined(HAVE_CONFIG_H) && HAVE_CONFIG_H
32 #include <config.h>
33 #endif
34 #include <com/sun/star/io/XStream.hpp>
35 #include <com/sun/star/container/XNameAccess.hpp>
36 #include <com/sun/star/document/XDocumentSubStorageSupplier.hpp>
37 #include <com/sun/star/embed/XStorage.hpp>
38 #include <com/sun/star/embed/ElementModes.hpp>
39 #include <comphelper/stl_types.hxx>
40 #include <comphelper/types.hxx>
41 #include "hsqldb/HStorageAccess.hxx"
42 #include "hsqldb/HStorageMap.hxx"
43 #include "hsqldb/StorageNativeInputStream.h"
44 
45 #include "jvmaccess/virtualmachine.hxx"
46 #include <com/sun/star/lang/XSingleComponentFactory.hpp>
47 #include "accesslog.hxx"
48 
49 #include <limits>
50 
51 
52 using namespace ::com::sun::star::container;
53 using namespace ::com::sun::star::uno;
54 using namespace ::com::sun::star::document;
55 using namespace ::com::sun::star::embed;
56 using namespace ::com::sun::star::io;
57 using namespace ::com::sun::star::lang;
58 using namespace ::connectivity::hsqldb;
59 
60 #define OUSTR(x) ::rtl::OUString( RTL_CONSTASCII_USTRINGPARAM(x) )
61 /*****************************************************************************/
62 /* exception macros */
63 
64 #define ThrowException(env, type, msg) { \
65 	env->ThrowNew(env->FindClass(type), msg); }
66 /*
67  * Class:     com_sun_star_sdbcx_comp_hsqldb_StorageNativeInputStream
68  * Method:    openStream
69  * Signature: (Ljava/lang/String;Ljava/lang/String;I)V
70  */
71 SAL_DLLPUBLIC_EXPORT void JNICALL Java_com_sun_star_sdbcx_comp_hsqldb_StorageNativeInputStream_openStream
72   (JNIEnv * env, jobject /*obj_this*/,jstring key, jstring name, jint mode)
73 {
74 #ifdef HSQLDB_DBG
75     {
76         OperationLogFile( env, name, "input" ).logOperation( "openStream" );
77         LogFile( env, name, "input" ).create();
78     }
79 #endif
80 	StorageContainer::registerStream(env,name,key,mode);
81 }
82 // -----------------------------------------------------------------------------
83 
84 /*
85  * Class:     com_sun_star_sdbcx_comp_hsqldb_StorageNativeInputStream
86  * Method:    read
87  * Signature: (Ljava/lang/String;Ljava/lang/String;)I
88  */
89 SAL_DLLPUBLIC_EXPORT jint JNICALL Java_com_sun_star_sdbcx_comp_hsqldb_StorageNativeInputStream_read__Ljava_lang_String_2Ljava_lang_String_2
90   (JNIEnv * env, jobject obj_this,jstring key, jstring name)
91 {
92 #ifdef HSQLDB_DBG
93     OperationLogFile( env, name, "input" ).logOperation( "read()" );
94 
95     DataLogFile aDataLog( env, name, "input" );
96     return read_from_storage_stream( env, obj_this, name, key, &aDataLog );
97 #else
98     return read_from_storage_stream( env, obj_this, name, key );
99 #endif
100 }
101 // -----------------------------------------------------------------------------
102 
103 /*
104  * Class:     com_sun_star_sdbcx_comp_hsqldb_StorageNativeInputStream
105  * Method:    read
106  * Signature: (Ljava/lang/String;Ljava/lang/String;[BII)I
107  */
108 SAL_DLLPUBLIC_EXPORT jint JNICALL Java_com_sun_star_sdbcx_comp_hsqldb_StorageNativeInputStream_read__Ljava_lang_String_2Ljava_lang_String_2_3BII
109   (JNIEnv * env, jobject obj_this,jstring key, jstring name, jbyteArray buffer, jint off, jint len)
110 {
111 #ifdef HSQLDB_DBG
112     OperationLogFile( env, name, "input" ).logOperation( "read( byte[], int, int )" );
113 
114     DataLogFile aDataLog( env, name, "input" );
115     return read_from_storage_stream_into_buffer( env, obj_this, name, key, buffer, off, len, &aDataLog );
116 #else
117     return read_from_storage_stream_into_buffer(env,obj_this,name,key,buffer,off,len);
118 #endif
119 }
120 // -----------------------------------------------------------------------------
121 
122 /*
123  * Class:     com_sun_star_sdbcx_comp_hsqldb_StorageNativeInputStream
124  * Method:    close
125  * Signature: (Ljava/lang/String;Ljava/lang/String;)V
126  */
127 SAL_DLLPUBLIC_EXPORT void JNICALL Java_com_sun_star_sdbcx_comp_hsqldb_StorageNativeInputStream_close
128   (JNIEnv * env, jobject /*obj_this*/,jstring key, jstring name)
129 {
130 #ifdef HSQLDB_DBG
131     OperationLogFile aOpLog( env, name, "input" );
132     aOpLog.logOperation( "close" );
133     aOpLog.close();
134 
135     LogFile aDataLog( env, name, "input" );
136     aDataLog.close();
137 #endif
138 	StorageContainer::revokeStream(env,name,key);
139 }
140 // -----------------------------------------------------------------------------
141 
142 /*
143  * Class:     com_sun_star_sdbcx_comp_hsqldb_StorageNativeInputStream
144  * Method:    skip
145  * Signature: (Ljava/lang/String;Ljava/lang/String;J)J
146  */
147 SAL_DLLPUBLIC_EXPORT jlong JNICALL Java_com_sun_star_sdbcx_comp_hsqldb_StorageNativeInputStream_skip
148   (JNIEnv * env, jobject /*obj_this*/,jstring key, jstring name, jlong n)
149 {
150 #ifdef HSQLDB_DBG
151     OperationLogFile( env, name, "input" ).logOperation( "skip()" );
152 #endif
153 
154     if ( n < 0 )
155         ThrowException(	env,
156 						"java/io/IOException",
157 						"n < 0");
158 
159 	::boost::shared_ptr<StreamHelper> pHelper = StorageContainer::getRegisteredStream(env,name,key);
160 	OSL_ENSURE(pHelper.get(),"No stream helper!");
161 	if ( pHelper.get() )
162 	{
163 		Reference<XInputStream> xIn = pHelper->getInputStream();
164 		if ( xIn.is() )
165 		{
166 			try
167 			{
168 				sal_Int64 tmpLongVal = n;
169 				sal_Int32 tmpIntVal;
170 
171                 try
172                 {
173 				    do {
174 					    if (tmpLongVal >= ::std::numeric_limits<sal_Int64>::max() )
175 						    tmpIntVal = ::std::numeric_limits<sal_Int32>::max();
176 					    else // Casting is safe here.
177 						    tmpIntVal = static_cast<sal_Int32>(tmpLongVal);
178 
179 					    tmpLongVal -= tmpIntVal;
180 
181                         xIn->skipBytes(tmpIntVal);
182 
183 				    } while (tmpLongVal > 0);
184                 }
185                 catch(Exception& )
186                 {
187                 }
188 
189                 return n - tmpLongVal;
190 			}
191 			catch(Exception& e)
192 			{
193 				OSL_ENSURE(0,"Exception catched! : skip();");
194                 StorageContainer::throwJavaException(e,env);
195 			}
196 		}
197 	}
198 	else
199 	{
200 		ThrowException(	env,
201 						"java/io/IOException",
202 						"Stream is not valid");
203 	}
204 	return 0;
205 }
206 // -----------------------------------------------------------------------------
207 
208 /*
209  * Class:     com_sun_star_sdbcx_comp_hsqldb_StorageNativeInputStream
210  * Method:    available
211  * Signature: (Ljava/lang/String;Ljava/lang/String;)I
212  */
213 SAL_DLLPUBLIC_EXPORT jint JNICALL Java_com_sun_star_sdbcx_comp_hsqldb_StorageNativeInputStream_available
214   (JNIEnv * env, jobject /*obj_this*/,jstring key, jstring name)
215 {
216 #ifdef HSQLDB_DBG
217     OperationLogFile aOpLog( env, name, "input" );
218     aOpLog.logOperation( "available" );
219 #endif
220 
221     ::boost::shared_ptr<StreamHelper> pHelper = StorageContainer::getRegisteredStream(env,name,key);
222 	OSL_ENSURE(pHelper.get(),"No stream helper!");
223 	Reference<XInputStream> xIn = pHelper.get() ? pHelper->getInputStream() : Reference<XInputStream>();
224 	if ( xIn.is() )
225 	{
226 		try
227 		{
228             jint nAvailable = xIn->available();
229 #ifdef HSQLDB_DBG
230             aOpLog.logReturn( nAvailable );
231 #endif
232 			return nAvailable;
233 		}
234 		catch(Exception& e)
235 		{
236            OSL_ENSURE(0,"Exception caught! : available();");
237 			StorageContainer::throwJavaException(e,env);
238 		}
239 	}
240 	else
241 	{
242 		ThrowException(	env,
243 						"java/io/IOException",
244 						"Stream is not valid");
245 	}
246 	return 0;
247 }
248 // -----------------------------------------------------------------------------
249 
250 /*
251  * Class:     com_sun_star_sdbcx_comp_hsqldb_StorageNativeInputStream
252  * Method:    read
253  * Signature: (Ljava/lang/String;Ljava/lang/String;[B)I
254  */
255 SAL_DLLPUBLIC_EXPORT jint JNICALL Java_com_sun_star_sdbcx_comp_hsqldb_StorageNativeInputStream_read__Ljava_lang_String_2Ljava_lang_String_2_3B
256   (JNIEnv * env, jobject /*obj_this*/,jstring key, jstring name, jbyteArray buffer)
257 {
258 #ifdef HSQLDB_DBG
259     OperationLogFile aOpLog( env, name, "input" );
260     aOpLog.logOperation( "read( byte[] )" );
261 
262     DataLogFile aDataLog( env, name, "input" );
263 #endif
264 
265     ::boost::shared_ptr<StreamHelper> pHelper = StorageContainer::getRegisteredStream(env,name,key);
266 	Reference< XInputStream> xIn = pHelper.get() ? pHelper->getInputStream() : Reference< XInputStream>();
267 	OSL_ENSURE(xIn.is(),"Input stream is NULL!");
268 	jint nBytesRead = 0;
269 	if ( xIn.is() )
270 	{
271 		jsize nLen = env->GetArrayLength(buffer);
272 		Sequence< ::sal_Int8 > aData(nLen);
273 
274         try
275         {
276 	        nBytesRead = xIn->readBytes(aData,nLen);
277         }
278         catch(Exception& e)
279 		{
280 			OSL_ENSURE(0,"Exception catched! : skip();");
281             StorageContainer::throwJavaException(e,env);
282 		}
283 
284 		// Casting bytesRead to an int is okay, since the user can
285 		// only pass in an integer length to read, so the bytesRead
286 		// must <= len.
287 		//
288 		if (nBytesRead <= 0) {
289 #ifdef HSQLDB_DBG
290             aOpLog.logReturn( (jint)-1 );
291 #endif
292 			return -1;
293 		}
294         OSL_ENSURE(nLen >= nBytesRead,"Buffer is too small!");
295         OSL_ENSURE(aData.getLength() >= nBytesRead,"Buffer is too small!");
296 		env->SetByteArrayRegion(buffer,0,nBytesRead,&aData[0]);
297 #ifdef HSQLDB_DBG
298         aDataLog.write( &aData[0], nBytesRead );
299 #endif
300 	}
301 #ifdef HSQLDB_DBG
302     aOpLog.logReturn( nBytesRead );
303 #endif
304 	return nBytesRead;
305 }
306 // -----------------------------------------------------------------------------
307