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 "java/sql/CallableStatement.hxx"
31 #include "java/tools.hxx"
32 #include "java/sql/Array.hxx"
33 #include "java/sql/Clob.hxx"
34 #include "java/sql/Blob.hxx"
35 #include "java/sql/Connection.hxx"
36 #include "java/sql/Ref.hxx"
37 #include "java/sql/Timestamp.hxx"
38 #include <cppuhelper/typeprovider.hxx>
39 #include <comphelper/sequence.hxx>
40 
41 #include <string.h>
42 
43 using namespace connectivity;
44 using namespace ::com::sun::star::uno;
45 using namespace ::com::sun::star::beans;
46 //	using namespace ::com::sun::star::sdbcx;
47 using namespace ::com::sun::star::sdbc;
48 using namespace ::com::sun::star::container;
49 using namespace ::com::sun::star::lang;
50 
51 
52 IMPLEMENT_SERVICE_INFO(java_sql_CallableStatement,"com.sun.star.sdbcx.ACallableStatement","com.sun.star.sdbc.CallableStatement");
53 
54 //**************************************************************
55 //************ Class: java.sql.CallableStatement
56 //**************************************************************
57 java_sql_CallableStatement::java_sql_CallableStatement( JNIEnv * pEnv, java_sql_Connection& _rCon,const ::rtl::OUString& sql )
58 	: java_sql_PreparedStatement( pEnv, _rCon, sql )
59 {
60 }
61 // -----------------------------------------------------------------------------
62 java_sql_CallableStatement::~java_sql_CallableStatement()
63 {
64 }
65 // -----------------------------------------------------------------------------
66 
67 Any SAL_CALL java_sql_CallableStatement::queryInterface( const Type & rType ) throw(RuntimeException)
68 {
69 	Any aRet = java_sql_PreparedStatement::queryInterface(rType);
70 	return aRet.hasValue() ? aRet : ::cppu::queryInterface(rType,static_cast< starsdbc::XRow*>(this),static_cast< starsdbc::XOutParameters*>(this));
71 }
72 // -------------------------------------------------------------------------
73 ::com::sun::star::uno::Sequence< ::com::sun::star::uno::Type > SAL_CALL java_sql_CallableStatement::getTypes(  ) throw(::com::sun::star::uno::RuntimeException)
74 {
75 	::cppu::OTypeCollection aTypes(	::getCppuType( (const ::com::sun::star::uno::Reference< starsdbc::XRow > *)0 ),
76 									::getCppuType( (const ::com::sun::star::uno::Reference< starsdbc::XOutParameters > *)0 ));
77 
78 	return ::comphelper::concatSequences(aTypes.getTypes(),java_sql_PreparedStatement::getTypes());
79 }
80 // -------------------------------------------------------------------------
81 sal_Bool SAL_CALL java_sql_CallableStatement::wasNull(  ) throw(starsdbc::SQLException, RuntimeException)
82 {
83     static jmethodID mID(NULL);
84     return callBooleanMethod( "wasNull", mID );
85 }
86 
87 sal_Bool SAL_CALL java_sql_CallableStatement::getBoolean( sal_Int32 columnIndex ) throw(starsdbc::SQLException, RuntimeException)
88 {
89     static jmethodID mID(NULL);
90     return callBooleanMethodWithIntArg( "getBoolean", mID,columnIndex );
91 }
92 sal_Int8 SAL_CALL java_sql_CallableStatement::getByte( sal_Int32 columnIndex ) throw(starsdbc::SQLException, RuntimeException)
93 {
94     SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Enviroment geloescht worden!");
95     createStatement(t.pEnv);
96     static jmethodID mID(NULL);
97     jbyte (JNIEnv::*pCallMethod)( jobject obj, jmethodID methodID, ... ) = &JNIEnv::CallByteMethod;
98     return callMethodWithIntArg<jbyte>(pCallMethod,"getByte","(I)B",mID,columnIndex);
99 }
100 Sequence< sal_Int8 > SAL_CALL java_sql_CallableStatement::getBytes( sal_Int32 columnIndex ) throw(starsdbc::SQLException, RuntimeException)
101 {
102     ::osl::MutexGuard aGuard( m_aMutex );
103 	checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed);
104 	Sequence< sal_Int8 > aSeq;
105 
106     SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Enviroment geloescht worden!");
107     createStatement(t.pEnv);
108     static jmethodID mID(NULL);
109     jbyteArray out = (jbyteArray)callObjectMethodWithIntArg(t.pEnv,"getBytes","(I)[B", mID, columnIndex);
110 	if (out)
111 	{
112 		jboolean p = sal_False;
113 		aSeq.realloc(t.pEnv->GetArrayLength(out));
114 		memcpy(aSeq.getArray(),t.pEnv->GetByteArrayElements(out,&p),aSeq.getLength());
115 		t.pEnv->DeleteLocalRef(out);
116 	}
117 	return aSeq;
118 }
119 ::com::sun::star::util::Date SAL_CALL java_sql_CallableStatement::getDate( sal_Int32 columnIndex ) throw(starsdbc::SQLException, RuntimeException)
120 {
121     SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Enviroment geloescht worden!");
122     createStatement(t.pEnv);
123     static jmethodID mID(NULL);
124     jobject out = callObjectMethodWithIntArg(t.pEnv,"getDate","(I)Ljava/sql/Date;", mID, columnIndex);
125 	return out ? static_cast <com::sun::star::util::Date>(java_sql_Date( t.pEnv, out )) : ::com::sun::star::util::Date();
126 }
127 double SAL_CALL java_sql_CallableStatement::getDouble( sal_Int32 columnIndex ) throw(starsdbc::SQLException, RuntimeException)
128 {
129     SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Enviroment geloescht worden!");
130     createStatement(t.pEnv);
131     static jmethodID mID(NULL);
132     double (JNIEnv::*pCallMethod)( jobject obj, jmethodID methodID, ... ) = &JNIEnv::CallDoubleMethod;
133     return callMethodWithIntArg<double>(pCallMethod,"getDouble","(I)D",mID,columnIndex);
134 }
135 
136 float SAL_CALL java_sql_CallableStatement::getFloat( sal_Int32 columnIndex ) throw(starsdbc::SQLException, RuntimeException)
137 {
138     SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Enviroment geloescht worden!");
139     createStatement(t.pEnv);
140     static jmethodID mID(NULL);
141     jfloat (JNIEnv::*pCallMethod)( jobject obj, jmethodID methodID, ... ) = &JNIEnv::CallFloatMethod;
142     return callMethodWithIntArg<jfloat>(pCallMethod,"getFloat","(I)F",mID,columnIndex);
143 }
144 
145 sal_Int32 SAL_CALL java_sql_CallableStatement::getInt( sal_Int32 columnIndex ) throw(starsdbc::SQLException, RuntimeException)
146 {
147     SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Enviroment geloescht worden!");
148     createStatement(t.pEnv);
149     static jmethodID mID(NULL);
150     return callIntMethodWithIntArg("getInt",mID,columnIndex);
151 }
152 
153 sal_Int64 SAL_CALL java_sql_CallableStatement::getLong( sal_Int32 columnIndex ) throw(starsdbc::SQLException, RuntimeException)
154 {
155     SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Enviroment geloescht worden!");
156     createStatement(t.pEnv);
157     static jmethodID mID(NULL);
158     jlong (JNIEnv::*pCallMethod)( jobject obj, jmethodID methodID, ... ) = &JNIEnv::CallLongMethod;
159     return callMethodWithIntArg<jlong>(pCallMethod,"getLong","(I)J",mID,columnIndex);
160 }
161 
162 Any SAL_CALL java_sql_CallableStatement::getObject( sal_Int32 columnIndex, const Reference< ::com::sun::star::container::XNameAccess >& /*typeMap*/ ) throw(starsdbc::SQLException, RuntimeException)
163 {
164     SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Enviroment geloescht worden!");
165     createStatement(t.pEnv);
166     static jmethodID mID(NULL);
167     /*jobject out = */callObjectMethodWithIntArg(t.pEnv,"getObject","(I)Ljava/lang/Object;", mID, columnIndex);
168 	// ACHTUNG: der Aufrufer wird Eigentuemer des zurueckgelieferten Zeigers !!!
169 	return Any(); //out==0 ? 0 : new java_lang_Object( t.pEnv, out );
170 }
171 
172 sal_Int16 SAL_CALL java_sql_CallableStatement::getShort( sal_Int32 columnIndex ) throw(starsdbc::SQLException, RuntimeException)
173 {
174     SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Enviroment geloescht worden!");
175     createStatement(t.pEnv);
176     static jmethodID mID(NULL);
177     jshort (JNIEnv::*pCallMethod)( jobject obj, jmethodID methodID, ... ) = &JNIEnv::CallShortMethod;
178     return callMethodWithIntArg<jshort>(pCallMethod,"getShort","(I)S",mID,columnIndex);
179 }
180 
181 ::rtl::OUString SAL_CALL java_sql_CallableStatement::getString( sal_Int32 columnIndex ) throw(starsdbc::SQLException, RuntimeException)
182 {
183     ::osl::MutexGuard aGuard( m_aMutex );
184 	checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed);
185     SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Enviroment geloescht worden!");
186 	createStatement(t.pEnv);
187     static jmethodID mID(NULL);
188     return callStringMethodWithIntArg("getString",mID,columnIndex);
189 }
190 
191  ::com::sun::star::util::Time SAL_CALL java_sql_CallableStatement::getTime( sal_Int32 columnIndex ) throw(starsdbc::SQLException, RuntimeException)
192 {
193     SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Enviroment geloescht worden!");
194     createStatement(t.pEnv);
195     static jmethodID mID(NULL);
196     jobject out = callObjectMethodWithIntArg(t.pEnv,"getTime","(I)Ljava/sql/Time;", mID, columnIndex);
197 	// ACHTUNG: der Aufrufer wird Eigentuemer des zurueckgelieferten Zeigers !!!
198 	return out ? static_cast <com::sun::star::util::Time> (java_sql_Time( t.pEnv, out )) : ::com::sun::star::util::Time();
199 }
200 
201  ::com::sun::star::util::DateTime SAL_CALL java_sql_CallableStatement::getTimestamp( sal_Int32 columnIndex ) throw(starsdbc::SQLException, RuntimeException)
202 {
203     SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Enviroment geloescht worden!");
204     createStatement(t.pEnv);
205     static jmethodID mID(NULL);
206     jobject out = callObjectMethodWithIntArg(t.pEnv,"getTimestamp","(I)Ljava/sql/Timestamp;", mID, columnIndex);
207 	// ACHTUNG: der Aufrufer wird Eigentuemer des zurueckgelieferten Zeigers !!!
208 	return out ? static_cast <com::sun::star::util::DateTime> (java_sql_Timestamp( t.pEnv, out )) : ::com::sun::star::util::DateTime();
209 }
210 
211 void SAL_CALL java_sql_CallableStatement::registerOutParameter( sal_Int32 parameterIndex, sal_Int32 sqlType, const ::rtl::OUString& typeName ) throw(starsdbc::SQLException, RuntimeException)
212 {
213     ::osl::MutexGuard aGuard( m_aMutex );
214 	checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed);
215     SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Enviroment geloescht worden!");
216 
217 	{
218 		createStatement(t.pEnv);
219 
220 		// temporaere Variable initialisieren
221 		static const char * cSignature = "(IILjava/lang/String;)V";
222 		static const char * cMethodName = "registerOutParameter";
223 		// Java-Call absetzen
224 		static jmethodID mID(NULL);
225         obtainMethodId(t.pEnv, cMethodName,cSignature, mID);
226 		// Parameter konvertieren
227 		jdbc::LocalRef< jstring > str( t.env(),convertwchar_tToJavaString(t.pEnv,typeName));
228 		t.pEnv->CallVoidMethod( object, mID, parameterIndex,sqlType,str.get());
229 		ThrowLoggedSQLException( m_aLogger, t.pEnv, *this );
230 	}
231 }
232 void SAL_CALL java_sql_CallableStatement::registerNumericOutParameter( sal_Int32 parameterIndex, sal_Int32 sqlType, sal_Int32 scale ) throw(::com::sun::star::sdbc::SQLException, ::com::sun::star::uno::RuntimeException)
233 {
234     ::osl::MutexGuard aGuard( m_aMutex );
235 	checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed);
236     SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Enviroment geloescht worden!");
237 
238 	{
239 		createStatement(t.pEnv);
240 		// temporaere Variable initialisieren
241 		static const char * cSignature = "(III)V";
242 		static const char * cMethodName = "registerOutParameter";
243 		// Java-Call absetzen
244 		static jmethodID mID(NULL);
245         obtainMethodId(t.pEnv, cMethodName,cSignature, mID);
246 		t.pEnv->CallVoidMethod( object, mID, parameterIndex,sqlType,scale);
247 		ThrowLoggedSQLException( m_aLogger, t.pEnv, *this );
248 	}
249 }
250 
251 jclass java_sql_CallableStatement::theClass = 0;
252 
253 jclass java_sql_CallableStatement::getMyClass() const
254 {
255 	// die Klasse muss nur einmal geholt werden, daher statisch
256 	if( !theClass )
257         theClass = findMyClass("java/sql/CallableStatement");
258 	return theClass;
259 }
260 
261 Reference< ::com::sun::star::io::XInputStream > SAL_CALL java_sql_CallableStatement::getBinaryStream( sal_Int32 columnIndex ) throw(starsdbc::SQLException, RuntimeException)
262 {
263 	Reference< starsdbc::XBlob > xBlob = getBlob(columnIndex);
264 	return xBlob.is() ? xBlob->getBinaryStream() : Reference< ::com::sun::star::io::XInputStream >();
265 }
266 Reference< ::com::sun::star::io::XInputStream > SAL_CALL java_sql_CallableStatement::getCharacterStream( sal_Int32 columnIndex ) throw(starsdbc::SQLException, RuntimeException)
267 {
268 	Reference< starsdbc::XClob > xClob = getClob(columnIndex);
269 	return xClob.is() ? xClob->getCharacterStream() : Reference< ::com::sun::star::io::XInputStream >();
270 }
271 
272 Reference< starsdbc::XArray > SAL_CALL java_sql_CallableStatement::getArray( sal_Int32 columnIndex ) throw(starsdbc::SQLException, RuntimeException)
273 {
274     SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Enviroment geloescht worden!");
275     createStatement(t.pEnv);
276     static jmethodID mID(NULL);
277     jobject out = callObjectMethodWithIntArg(t.pEnv,"getArray","(I)Ljava/sql/Array;", mID, columnIndex);
278 	// ACHTUNG: der Aufrufer wird Eigentuemer des zurueckgelieferten Zeigers !!!
279 	return out==0 ? 0 : new java_sql_Array( t.pEnv, out );
280 }
281 
282 Reference< starsdbc::XClob > SAL_CALL java_sql_CallableStatement::getClob( sal_Int32 columnIndex ) throw(starsdbc::SQLException, RuntimeException)
283 {
284     SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Enviroment geloescht worden!");
285     createStatement(t.pEnv);
286     static jmethodID mID(NULL);
287     jobject out = callObjectMethodWithIntArg(t.pEnv,"getClob","(I)Ljava/sql/Clob;", mID, columnIndex);
288 	// ACHTUNG: der Aufrufer wird Eigentuemer des zurueckgelieferten Zeigers !!!
289 	return out==0 ? 0 : new java_sql_Clob( t.pEnv, out );
290 }
291 Reference< starsdbc::XBlob > SAL_CALL java_sql_CallableStatement::getBlob( sal_Int32 columnIndex ) throw(starsdbc::SQLException, RuntimeException)
292 {
293     SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Enviroment geloescht worden!");
294     createStatement(t.pEnv);
295     static jmethodID mID(NULL);
296     jobject out = callObjectMethodWithIntArg(t.pEnv,"getBlob","(I)Ljava/sql/Blob;", mID, columnIndex);
297 	// ACHTUNG: der Aufrufer wird Eigentuemer des zurueckgelieferten Zeigers !!!
298 	return out==0 ? 0 : new java_sql_Blob( t.pEnv, out );
299 }
300 
301 Reference< starsdbc::XRef > SAL_CALL java_sql_CallableStatement::getRef( sal_Int32 columnIndex ) throw(starsdbc::SQLException, RuntimeException)
302 {
303     SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Enviroment geloescht worden!");
304     createStatement(t.pEnv);
305     static jmethodID mID(NULL);
306     jobject out = callObjectMethodWithIntArg(t.pEnv,"getRef","(I)Ljava/sql/Ref;", mID, columnIndex);
307 	// ACHTUNG: der Aufrufer wird Eigentuemer des zurueckgelieferten Zeigers !!!
308 	return out==0 ? 0 : new java_sql_Ref( t.pEnv, out );
309 }
310 // -----------------------------------------------------------------------------
311 void SAL_CALL java_sql_CallableStatement::acquire() throw()
312 {
313 	java_sql_PreparedStatement::acquire();
314 }
315 // -----------------------------------------------------------------------------
316 void SAL_CALL java_sql_CallableStatement::release() throw()
317 {
318 	java_sql_PreparedStatement::release();
319 }
320 // -----------------------------------------------------------------------------
321 void java_sql_CallableStatement::createStatement(JNIEnv* /*_pEnv*/)
322 {
323 	::osl::MutexGuard aGuard( m_aMutex );
324 	checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed);
325 
326 
327     SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Enviroment geloescht worden!");
328 	if( t.pEnv && !object ){
329 		// temporaere Variable initialisieren
330 		static const char * cSignature = "(Ljava/lang/String;II)Ljava/sql/CallableStatement;";
331 		static const char * cMethodName = "prepareCall";
332 		// Java-Call absetzen
333 		jobject out = NULL;
334 		// Parameter konvertieren
335 		jdbc::LocalRef< jstring > str( t.env(),convertwchar_tToJavaString(t.pEnv,m_sSqlStatement));
336 
337 		static jmethodID mID(NULL);
338 		if ( !mID  )
339 			mID  = t.pEnv->GetMethodID( m_pConnection->getMyClass(), cMethodName, cSignature );
340 		if( mID ){
341 			out = t.pEnv->CallObjectMethod( m_pConnection->getJavaObject(), mID, str.get() ,m_nResultSetType,m_nResultSetConcurrency);
342 		} //mID
343 		else
344 		{
345 			static const char * cSignature2 = "(Ljava/lang/String;)Ljava/sql/CallableStatement;";
346 			static jmethodID mID2 = t.pEnv->GetMethodID( m_pConnection->getMyClass(), cMethodName, cSignature2 );OSL_ENSURE(mID2,"Unknown method id!");
347 			if( mID2 ){
348 				out = t.pEnv->CallObjectMethod( m_pConnection->getJavaObject(), mID2, str.get() );
349 			} //mID
350 		}
351 		ThrowLoggedSQLException( m_aLogger, t.pEnv, *this );
352 
353 		if ( out )
354 			object = t.pEnv->NewGlobalRef( out );
355 	} //t.pEnv
356 }
357 // -----------------------------------------------------------------------------
358 
359 
360