diff options
Diffstat (limited to 'connectivity/source/drivers/jdbc')
31 files changed, 8191 insertions, 0 deletions
diff --git a/connectivity/source/drivers/jdbc/Array.cxx b/connectivity/source/drivers/jdbc/Array.cxx new file mode 100644 index 000000000..d03b01928 --- /dev/null +++ b/connectivity/source/drivers/jdbc/Array.cxx @@ -0,0 +1,132 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <java/sql/Array.hxx> +#include <java/tools.hxx> +#include <osl/diagnose.h> + +using namespace connectivity; + +//************ Class: java.sql.Array + + +jclass java_sql_Array::theClass = nullptr; + +java_sql_Array::~java_sql_Array() +{} + +jclass java_sql_Array::getMyClass() const +{ + // the class must be fetched once, therefore it's static + if( !theClass ) + theClass = findMyClass("java/sql/Array"); + + return theClass; +} + +OUString SAL_CALL java_sql_Array::getBaseTypeName( ) +{ + static jmethodID mID(nullptr); + return callStringMethod("getBaseTypeName",mID); +} + +sal_Int32 SAL_CALL java_sql_Array::getBaseType( ) +{ + static jmethodID mID(nullptr); + return callIntMethod_ThrowSQL("getBaseType", mID); +} + +css::uno::Sequence< css::uno::Any > SAL_CALL java_sql_Array::getArray( const css::uno::Reference< css::container::XNameAccess >& typeMap ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + { + jobject obj = convertTypeMapToJavaMap(typeMap); + static const char * const cSignature = "(Ljava/util/Map;)[Ljava/lang/Object;"; + static const char * const cMethodName = "getArray"; + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + // submit Java-Call + t.pEnv->CallObjectMethod( object, mID, obj); + ThrowSQLException(t.pEnv,*this); + // and clean up + t.pEnv->DeleteLocalRef(obj); + } //t.pEnv + return css::uno::Sequence< css::uno::Any >(); +} + +css::uno::Sequence< css::uno::Any > SAL_CALL java_sql_Array::getArrayAtIndex( sal_Int32 index, sal_Int32 count, const css::uno::Reference< css::container::XNameAccess >& typeMap ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + { + jobject obj = convertTypeMapToJavaMap(typeMap); + static const char * const cSignature = "(IILjava/util/Map;)[Ljava/lang/Object;"; + static const char * const cMethodName = "getArray"; + // submit Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + t.pEnv->CallObjectMethod( object, mID, index,count,obj); + ThrowSQLException(t.pEnv,*this); + // and clean up + t.pEnv->DeleteLocalRef(obj); + } + return css::uno::Sequence< css::uno::Any >(); +} + +css::uno::Reference< css::sdbc::XResultSet > SAL_CALL java_sql_Array::getResultSet( const css::uno::Reference< css::container::XNameAccess >& typeMap ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + { + // convert Parameter + jobject obj = convertTypeMapToJavaMap(typeMap); + // initialize temporary variable + static const char * const cSignature = "(Ljava/util/Map;)Ljava/sql/ResultSet;"; + static const char * const cMethodName = "getResultSet"; + // submit Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + t.pEnv->CallObjectMethod( object, mID, obj); + ThrowSQLException(t.pEnv,*this); + // and cleanup + t.pEnv->DeleteLocalRef(obj); + } + return nullptr; +} + +css::uno::Reference< css::sdbc::XResultSet > SAL_CALL java_sql_Array::getResultSetAtIndex( sal_Int32 index, sal_Int32 count, const css::uno::Reference< css::container::XNameAccess >& typeMap ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + { + // convert parameter + jobject obj = convertTypeMapToJavaMap(typeMap); + // initialize temporary variable + static const char * const cSignature = "(Ljava/util/Map;)Ljava/sql/ResultSet;"; + static const char * const cMethodName = "getResultSetAtIndex"; + // submit Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + t.pEnv->CallObjectMethod( object, mID, index,count,obj); + ThrowSQLException(t.pEnv,*this); + // and cleanup + t.pEnv->DeleteLocalRef(obj); + } + return nullptr; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/Blob.cxx b/connectivity/source/drivers/jdbc/Blob.cxx new file mode 100644 index 000000000..adacd5d7c --- /dev/null +++ b/connectivity/source/drivers/jdbc/Blob.cxx @@ -0,0 +1,144 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <java/sql/Blob.hxx> +#include <java/io/InputStream.hxx> +#include <connectivity/dbexception.hxx> +#include <osl/diagnose.h> + +#include <string.h> + +using namespace connectivity; + +//************ Class: java.sql.Blob + + +jclass java_sql_Blob::theClass = nullptr; +java_sql_Blob::java_sql_Blob( JNIEnv * pEnv, jobject myObj ) + : java_lang_Object( pEnv, myObj ) +{ + SDBThreadAttach::addRef(); +} +java_sql_Blob::~java_sql_Blob() +{ + SDBThreadAttach::releaseRef(); +} + +jclass java_sql_Blob::getMyClass() const +{ + // the class must be fetched only once, therefore it's static + if( !theClass ) + theClass = findMyClass("java/sql/Blob"); + return theClass; +} + +sal_Int64 SAL_CALL java_sql_Blob::length( ) +{ + jlong out(0); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + + { + // initialize temporary variable + static const char * const cSignature = "()J"; + static const char * const cMethodName = "length"; + // submit Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + out = t.pEnv->CallLongMethod( object, mID ); + ThrowSQLException(t.pEnv,*this); + } //t.pEnv + return static_cast<sal_Int64>(out); +} +css::uno::Sequence< sal_Int8 > SAL_CALL java_sql_Blob::getBytes( sal_Int64 pos, sal_Int32 count ) +{ + + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + css::uno::Sequence< sal_Int8 > aSeq; + { + // initialize temporary variable + static const char * const cSignature = "(JI)[B"; + static const char * const cMethodName = "getBytes"; + // submit Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + jbyteArray out = static_cast<jbyteArray>(t.pEnv->CallObjectMethod( object, mID,pos,count)); + ThrowSQLException(t.pEnv,*this); + if(out) + { + jboolean p = false; + aSeq.realloc(t.pEnv->GetArrayLength(out)); + memcpy(aSeq.getArray(),t.pEnv->GetByteArrayElements(out,&p),aSeq.getLength()); + t.pEnv->DeleteLocalRef(out); + } + } //t.pEnv + // WARNING: the caller becomes the owner of the returned pointer + return aSeq; +} + +css::uno::Reference< css::io::XInputStream > SAL_CALL java_sql_Blob::getBinaryStream( ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + static jmethodID mID(nullptr); + jobject out = callObjectMethod(t.pEnv,"getBinaryStream","()Ljava/io/InputStream;", mID); + // WARNING: the caller becomes the owner of the returned pointer + return out==nullptr ? nullptr : new java_io_InputStream( t.pEnv, out ); +} + +sal_Int64 SAL_CALL java_sql_Blob::position( const css::uno::Sequence< sal_Int8 >& pattern, sal_Int64 start ) +{ + jlong out(0); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + + { + // initialize temporary variable + static const char * const cSignature = "([BI)J"; + static const char * const cMethodName = "position"; + // submit Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + // convert Parameter + jbyteArray pByteArray = t.pEnv->NewByteArray(pattern.getLength()); + jbyte * patternData = reinterpret_cast<jbyte *>( + const_cast<sal_Int8 *>(pattern.getConstArray())); + // 4th param of Set*ArrayRegion changed from pointer to non-const to + // pointer to const between <http://docs.oracle.com/javase/6/docs/ + // technotes/guides/jni/spec/functions.html#wp22933> and + // <http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/ + // functions.html#wp22933>; work around that difference in a way + // that doesn't trigger loplugin:redundantcast + t.pEnv->SetByteArrayRegion(pByteArray,0,pattern.getLength(),patternData); + out = t.pEnv->CallLongMethod( object, mID, pByteArray,start ); + t.pEnv->DeleteLocalRef(pByteArray); + ThrowSQLException(t.pEnv,*this); + } //t.pEnv + return static_cast<sal_Int64>(out); +} + +sal_Int64 SAL_CALL java_sql_Blob::positionOfBlob( const css::uno::Reference< css::sdbc::XBlob >& /*pattern*/, sal_Int64 /*start*/ ) +{ + ::dbtools::throwFeatureNotImplementedSQLException( "XBlob::positionOfBlob", *this ); + // this was put here in CWS warnings01. The previous implementation was defective, as it did ignore + // the pattern parameter. Since the effort for proper implementation is rather high - we would need + // to translated patter into a byte[] -, we defer this functionality for the moment (hey, it was + // unusable, anyway) + // #i57457# + return 0; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/Boolean.cxx b/connectivity/source/drivers/jdbc/Boolean.cxx new file mode 100644 index 000000000..acd1e81ef --- /dev/null +++ b/connectivity/source/drivers/jdbc/Boolean.cxx @@ -0,0 +1,43 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <java/lang/Boolean.hxx> +using namespace connectivity; + +//************ Class: java.lang.Boolean + + +jclass java_lang_Boolean::theClass = nullptr; + +java_lang_Boolean::~java_lang_Boolean() +{} +jclass java_lang_Boolean::st_getMyClass() +{ + // the class must be fetched only once, therefore static + if( !theClass ) + theClass = findMyClass("java/lang/Boolean"); + return theClass; +} + +jclass java_lang_Boolean::getMyClass() const +{ + return st_getMyClass(); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/CallableStatement.cxx b/connectivity/source/drivers/jdbc/CallableStatement.cxx new file mode 100644 index 000000000..0994c827e --- /dev/null +++ b/connectivity/source/drivers/jdbc/CallableStatement.cxx @@ -0,0 +1,354 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <java/sql/CallableStatement.hxx> +#include <java/tools.hxx> +#include <java/sql/Array.hxx> +#include <java/sql/Clob.hxx> +#include <java/sql/Blob.hxx> +#include <java/sql/Connection.hxx> +#include <java/sql/Ref.hxx> +#include <java/sql/Timestamp.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <comphelper/sequence.hxx> + +#include <string.h> + +using namespace connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; + + +IMPLEMENT_SERVICE_INFO(java_sql_CallableStatement,"com.sun.star.sdbcx.ACallableStatement","com.sun.star.sdbc.CallableStatement"); + + +//************ Class: java.sql.CallableStatement + +java_sql_CallableStatement::java_sql_CallableStatement( JNIEnv * pEnv, java_sql_Connection& _rCon,const OUString& sql ) + : java_sql_PreparedStatement( pEnv, _rCon, sql ) +{ +} + +java_sql_CallableStatement::~java_sql_CallableStatement() +{ +} + + +Any SAL_CALL java_sql_CallableStatement::queryInterface( const Type & rType ) +{ + Any aRet = java_sql_PreparedStatement::queryInterface(rType); + return aRet.hasValue() ? aRet : ::cppu::queryInterface(rType,static_cast< css::sdbc::XRow*>(this),static_cast< css::sdbc::XOutParameters*>(this)); +} + +css::uno::Sequence< css::uno::Type > SAL_CALL java_sql_CallableStatement::getTypes( ) +{ + ::cppu::OTypeCollection aTypes( cppu::UnoType<css::sdbc::XRow>::get(), + cppu::UnoType<css::sdbc::XOutParameters>::get()); + + return ::comphelper::concatSequences(aTypes.getTypes(),java_sql_PreparedStatement::getTypes()); +} + +sal_Bool SAL_CALL java_sql_CallableStatement::wasNull( ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + return callBooleanMethod( "wasNull", mID ); +} + +sal_Bool SAL_CALL java_sql_CallableStatement::getBoolean( sal_Int32 columnIndex ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + return callBooleanMethodWithIntArg( "getBoolean", mID,columnIndex ); +} +sal_Int8 SAL_CALL java_sql_CallableStatement::getByte( sal_Int32 columnIndex ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + jbyte (JNIEnv::* const pCallMethod)( jobject obj, jmethodID methodID, ... ) = &JNIEnv::CallByteMethod; + return callMethodWithIntArg<jbyte>(pCallMethod,"getByte","(I)B",mID,columnIndex); +} +Sequence< sal_Int8 > SAL_CALL java_sql_CallableStatement::getBytes( sal_Int32 columnIndex ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + Sequence< sal_Int8 > aSeq; + + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + jbyteArray out = static_cast<jbyteArray>(callObjectMethodWithIntArg(t.pEnv,"getBytes","(I)[B", mID, columnIndex)); + if (out) + { + jboolean p = false; + aSeq.realloc(t.pEnv->GetArrayLength(out)); + memcpy(aSeq.getArray(),t.pEnv->GetByteArrayElements(out,&p),aSeq.getLength()); + t.pEnv->DeleteLocalRef(out); + } + return aSeq; +} +css::util::Date SAL_CALL java_sql_CallableStatement::getDate( sal_Int32 columnIndex ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + jobject out = callObjectMethodWithIntArg(t.pEnv,"getDate","(I)Ljava/sql/Date;", mID, columnIndex); + return out ? static_cast <css::util::Date>(java_sql_Date( t.pEnv, out )) : css::util::Date(); +} +double SAL_CALL java_sql_CallableStatement::getDouble( sal_Int32 columnIndex ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + double (JNIEnv::* const pCallMethod)( jobject obj, jmethodID methodID, ... ) = &JNIEnv::CallDoubleMethod; + return callMethodWithIntArg<double>(pCallMethod,"getDouble","(I)D",mID,columnIndex); +} + +float SAL_CALL java_sql_CallableStatement::getFloat( sal_Int32 columnIndex ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + jfloat (JNIEnv::* const pCallMethod)( jobject obj, jmethodID methodID, ... ) = &JNIEnv::CallFloatMethod; + return callMethodWithIntArg<jfloat>(pCallMethod,"getFloat","(I)F",mID,columnIndex); +} + +sal_Int32 SAL_CALL java_sql_CallableStatement::getInt( sal_Int32 columnIndex ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + return callIntMethodWithIntArg_ThrowSQL("getInt",mID,columnIndex); +} + +sal_Int64 SAL_CALL java_sql_CallableStatement::getLong( sal_Int32 columnIndex ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + jlong (JNIEnv::* const pCallMethod)( jobject obj, jmethodID methodID, ... ) = &JNIEnv::CallLongMethod; + return callMethodWithIntArg<jlong>(pCallMethod,"getLong","(I)J",mID,columnIndex); +} + +Any SAL_CALL java_sql_CallableStatement::getObject( sal_Int32 columnIndex, const Reference< css::container::XNameAccess >& /*typeMap*/ ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + callObjectMethodWithIntArg(t.pEnv,"getObject","(I)Ljava/lang/Object;", mID, columnIndex); + // WARNING: the caller becomes the owner of the returned pointer + return Any(); +} + +sal_Int16 SAL_CALL java_sql_CallableStatement::getShort( sal_Int32 columnIndex ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + jshort (JNIEnv::* const pCallMethod)( jobject obj, jmethodID methodID, ... ) = &JNIEnv::CallShortMethod; + return callMethodWithIntArg<jshort>(pCallMethod,"getShort","(I)S",mID,columnIndex); +} + +OUString SAL_CALL java_sql_CallableStatement::getString( sal_Int32 columnIndex ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + return callStringMethodWithIntArg("getString",mID,columnIndex); +} + + css::util::Time SAL_CALL java_sql_CallableStatement::getTime( sal_Int32 columnIndex ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + jobject out = callObjectMethodWithIntArg(t.pEnv,"getTime","(I)Ljava/sql/Time;", mID, columnIndex); + // WARNING: the caller becomes the owner of the returned pointer + return out ? static_cast <css::util::Time> (java_sql_Time( t.pEnv, out )) : css::util::Time(); +} + + css::util::DateTime SAL_CALL java_sql_CallableStatement::getTimestamp( sal_Int32 columnIndex ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + jobject out = callObjectMethodWithIntArg(t.pEnv,"getTimestamp","(I)Ljava/sql/Timestamp;", mID, columnIndex); + // WARNING: the caller becomes the owner of the returned pointer + return out ? static_cast <css::util::DateTime> (java_sql_Timestamp( t.pEnv, out )) : css::util::DateTime(); +} + +void SAL_CALL java_sql_CallableStatement::registerOutParameter( sal_Int32 parameterIndex, sal_Int32 sqlType, const OUString& typeName ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + + { + createStatement(t.pEnv); + + // initialize temporary variable + static const char * const cSignature = "(IILjava/lang/String;)V"; + static const char * const cMethodName = "registerOutParameter"; + // execute Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + // Convert Parameter + jdbc::LocalRef< jstring > str( t.env(),convertwchar_tToJavaString(t.pEnv,typeName)); + t.pEnv->CallVoidMethod( object, mID, parameterIndex,sqlType,str.get()); + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + } +} +void SAL_CALL java_sql_CallableStatement::registerNumericOutParameter( sal_Int32 parameterIndex, sal_Int32 sqlType, sal_Int32 scale ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + + { + createStatement(t.pEnv); + // initialize temporary variable + static const char * const cSignature = "(III)V"; + static const char * const cMethodName = "registerOutParameter"; + // execute Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + t.pEnv->CallVoidMethod( object, mID, parameterIndex,sqlType,scale); + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + } +} + +jclass java_sql_CallableStatement::theClass = nullptr; + +jclass java_sql_CallableStatement::getMyClass() const +{ + // the class must be fetched only once, therefore static + if( !theClass ) + theClass = findMyClass("java/sql/CallableStatement"); + return theClass; +} + +Reference< css::io::XInputStream > SAL_CALL java_sql_CallableStatement::getBinaryStream( sal_Int32 columnIndex ) +{ + Reference< css::sdbc::XBlob > xBlob = getBlob(columnIndex); + return xBlob.is() ? xBlob->getBinaryStream() : Reference< css::io::XInputStream >(); +} +Reference< css::io::XInputStream > SAL_CALL java_sql_CallableStatement::getCharacterStream( sal_Int32 columnIndex ) +{ + Reference< css::sdbc::XClob > xClob = getClob(columnIndex); + return xClob.is() ? xClob->getCharacterStream() : Reference< css::io::XInputStream >(); +} + +Reference< css::sdbc::XArray > SAL_CALL java_sql_CallableStatement::getArray( sal_Int32 columnIndex ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + jobject out = callObjectMethodWithIntArg(t.pEnv,"getArray","(I)Ljava/sql/Array;", mID, columnIndex); + // WARNING: the caller becomes the owner of the returned pointer + return out==nullptr ? nullptr : new java_sql_Array( t.pEnv, out ); +} + +Reference< css::sdbc::XClob > SAL_CALL java_sql_CallableStatement::getClob( sal_Int32 columnIndex ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + jobject out = callObjectMethodWithIntArg(t.pEnv,"getClob","(I)Ljava/sql/Clob;", mID, columnIndex); + // WARNING: the caller becomes the owner of the returned pointer + return out==nullptr ? nullptr : new java_sql_Clob( t.pEnv, out ); +} +Reference< css::sdbc::XBlob > SAL_CALL java_sql_CallableStatement::getBlob( sal_Int32 columnIndex ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + jobject out = callObjectMethodWithIntArg(t.pEnv,"getBlob","(I)Ljava/sql/Blob;", mID, columnIndex); + // WARNING: the caller becomes the owner of the returned pointer + return out==nullptr ? nullptr : new java_sql_Blob( t.pEnv, out ); +} + +Reference< css::sdbc::XRef > SAL_CALL java_sql_CallableStatement::getRef( sal_Int32 columnIndex ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + jobject out = callObjectMethodWithIntArg(t.pEnv,"getRef","(I)Ljava/sql/Ref;", mID, columnIndex); + // WARNING: the caller becomes the owner of the returned pointer + return out==nullptr ? nullptr : new java_sql_Ref( t.pEnv, out ); +} + +void SAL_CALL java_sql_CallableStatement::acquire() throw() +{ + java_sql_PreparedStatement::acquire(); +} + +void SAL_CALL java_sql_CallableStatement::release() throw() +{ + java_sql_PreparedStatement::release(); +} + +void java_sql_CallableStatement::createStatement(JNIEnv* /*_pEnv*/) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + if( !(t.pEnv && !object) ) + return; + + // initialize temporary variable + static const char * const cMethodName = "prepareCall"; + // execute Java-Call + jobject out = nullptr; + // convert Parameter + jdbc::LocalRef< jstring > str( t.env(),convertwchar_tToJavaString(t.pEnv,m_sSqlStatement)); + + static jmethodID mID = [&]() + { + static const char * const cSignature = "(Ljava/lang/String;II)Ljava/sql/CallableStatement;"; + return t.pEnv->GetMethodID( m_pConnection->getMyClass(), cMethodName, cSignature ); + }(); + if( mID ){ + out = t.pEnv->CallObjectMethod( m_pConnection->getJavaObject(), mID, str.get() ,m_nResultSetType,m_nResultSetConcurrency); + } //mID + else + { + static const char * const cSignature2 = "(Ljava/lang/String;)Ljava/sql/CallableStatement;"; + static jmethodID mID2 = t.pEnv->GetMethodID( m_pConnection->getMyClass(), cMethodName, cSignature2 );OSL_ENSURE(mID2,"Unknown method id!"); + if( mID2 ){ + out = t.pEnv->CallObjectMethod( m_pConnection->getJavaObject(), mID2, str.get() ); + } //mID + } + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + + if ( out ) + object = t.pEnv->NewGlobalRef( out ); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/Class.cxx b/connectivity/source/drivers/jdbc/Class.cxx new file mode 100644 index 000000000..98d37fbcc --- /dev/null +++ b/connectivity/source/drivers/jdbc/Class.cxx @@ -0,0 +1,70 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <java/lang/Class.hxx> +#include <rtl/ustring.hxx> + +using namespace connectivity; + +//************ Class: java.lang.Class + + +jclass java_lang_Class::theClass = nullptr; + +java_lang_Class::~java_lang_Class() +{} + +jclass java_lang_Class::getMyClass() const +{ + // the class must be fetched only once, therefore static + if( !theClass ) + theClass = findMyClass("java/lang/Class"); + return theClass; +} + +java_lang_Class * java_lang_Class::forName( const OUString& _par0 ) +{ + jobject out(nullptr); + SDBThreadAttach t; + + { + OString sClassName = OUStringToOString(_par0, RTL_TEXTENCODING_JAVA_UTF8); + sClassName = sClassName.replace('.','/'); + out = t.pEnv->FindClass(sClassName.getStr()); + ThrowSQLException(t.pEnv,nullptr); + } //t.pEnv + // WARNING: the caller becomes the owner of the returned pointer + return out==nullptr ? nullptr : new java_lang_Class( t.pEnv, out ); +} + +jobject java_lang_Class::newInstanceObject() +{ + SDBThreadAttach t; + auto const id = t.pEnv->GetMethodID(static_cast<jclass>(object), "<init>", "()V"); + if (id == nullptr) { + ThrowSQLException(t.pEnv, nullptr); + } + auto const obj = t.pEnv->NewObject(static_cast<jclass>(object), id); + if (obj == nullptr) { + ThrowSQLException(t.pEnv, nullptr); + } + return obj; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/Clob.cxx b/connectivity/source/drivers/jdbc/Clob.cxx new file mode 100644 index 000000000..135512d5a --- /dev/null +++ b/connectivity/source/drivers/jdbc/Clob.cxx @@ -0,0 +1,132 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <java/sql/Clob.hxx> +#include <java/tools.hxx> +#include <java/io/Reader.hxx> +#include <connectivity/dbexception.hxx> +#include <osl/diagnose.h> + +using namespace connectivity; + +//************ Class: java.sql.Clob + + +jclass java_sql_Clob::theClass = nullptr; + +java_sql_Clob::java_sql_Clob( JNIEnv * pEnv, jobject myObj ) + : java_lang_Object( pEnv, myObj ) +{ + SDBThreadAttach::addRef(); +} +java_sql_Clob::~java_sql_Clob() +{ + SDBThreadAttach::releaseRef(); +} + +jclass java_sql_Clob::getMyClass() const +{ + // the class must be fetched only once, therefore static + if( !theClass ) + theClass = findMyClass("java/sql/Clob"); + return theClass; +} + +sal_Int64 SAL_CALL java_sql_Clob::length( ) +{ + jlong out(0); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + + { + // initialize temporary variable + static const char * const cSignature = "()J"; + static const char * const cMethodName = "length"; + // execute Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + out = t.pEnv->CallLongMethod( object, mID ); + ThrowSQLException(t.pEnv,*this); + } //t.pEnv + return static_cast<sal_Int64>(out); +} + +OUString SAL_CALL java_sql_Clob::getSubString( sal_Int64 pos, sal_Int32 subStringLength ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + OUString aStr; + { + // initialize temporary variable + static const char * const cSignature = "(JI)Ljava/lang/String;"; + static const char * const cMethodName = "getSubString"; + // execute Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + jstring out = static_cast<jstring>(t.pEnv->CallObjectMethod( object, mID,pos,subStringLength)); + ThrowSQLException(t.pEnv,*this); + aStr = JavaString2String(t.pEnv,out); + } //t.pEnv + // WARNING: the caller becomes the owner of the returned pointer + return aStr; +} + +css::uno::Reference< css::io::XInputStream > SAL_CALL java_sql_Clob::getCharacterStream( ) +{ + SDBThreadAttach t; + static jmethodID mID(nullptr); + jobject out = callObjectMethod(t.pEnv,"getCharacterStream","()Ljava/io/Reader;", mID); + + // WARNING: the caller becomes the owner of the returned pointer + return out==nullptr ? nullptr : new java_io_Reader( t.pEnv, out ); +} + +sal_Int64 SAL_CALL java_sql_Clob::position( const OUString& searchstr, sal_Int32 start ) +{ + jlong out(0); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + + { + jvalue args[1]; + // convert Parameter + args[0].l = convertwchar_tToJavaString(t.pEnv,searchstr); + // initialize temporary Variable + static const char * const cSignature = "(Ljava/lang/String;I)J"; + static const char * const cMethodName = "position"; + // execute Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + out = t.pEnv->CallLongMethod( object, mID, args[0].l,start ); + ThrowSQLException(t.pEnv,*this); + t.pEnv->DeleteLocalRef(static_cast<jstring>(args[0].l)); + } //t.pEnv + return static_cast<sal_Int64>(out); +} + +sal_Int64 SAL_CALL java_sql_Clob::positionOfClob( const css::uno::Reference< css::sdbc::XClob >& /*pattern*/, sal_Int64 /*start*/ ) +{ + ::dbtools::throwFeatureNotImplementedSQLException( "XClob::positionOfClob", *this ); + // this was put here in CWS warnings01. The previous implementation was defective, as it did ignore + // the pattern parameter. Since the effort for proper implementation is rather high - we would need + // to translated patter into a byte[] -, we defer this functionality for the moment (hey, it was + // unusable, anyway) + // 2005-11-15 / #i57457# / frank.schoenheit@sun.com + return 0; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/ConnectionLog.cxx b/connectivity/source/drivers/jdbc/ConnectionLog.cxx new file mode 100644 index 000000000..96a82fb61 --- /dev/null +++ b/connectivity/source/drivers/jdbc/ConnectionLog.cxx @@ -0,0 +1,110 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <java/sql/ConnectionLog.hxx> + +#include <com/sun/star/util/Date.hpp> +#include <com/sun/star/util/Time.hpp> +#include <com/sun/star/util/DateTime.hpp> + +#include <stdio.h> + + +namespace connectivity::java::sql { + + + namespace + { + sal_Int32 lcl_getFreeID( ConnectionLog::ObjectType _eType ) + { + static oslInterlockedCount s_nCounts[ ConnectionLog::ObjectTypeCount ] = { 0, 0 }; + return osl_atomic_increment( s_nCounts + _eType ); + } + } + + ConnectionLog::ConnectionLog( const ::comphelper::EventLogger& _rDriverLog ) + :ConnectionLog_Base( _rDriverLog ) + ,m_nObjectID( lcl_getFreeID( CONNECTION ) ) + { + } + + + ConnectionLog::ConnectionLog( const ConnectionLog& _rSourceLog ) + :ConnectionLog_Base( _rSourceLog ) + ,m_nObjectID( _rSourceLog.m_nObjectID ) + { + } + + + ConnectionLog::ConnectionLog( const ConnectionLog& _rSourceLog, ConnectionLog::ObjectType _eType ) + :ConnectionLog_Base( _rSourceLog ) + ,m_nObjectID( lcl_getFreeID( _eType ) ) + { + } + + +} // namespace connectivity::java::sql + + +namespace comphelper::log::convert +{ + + + using ::com::sun::star::util::Date; + using ::com::sun::star::util::Time; + using ::com::sun::star::util::DateTime; + + + OUString convertLogArgToString( const Date& _rDate ) + { + char buffer[ 30 ]; + const size_t buffer_size = sizeof( buffer ); + snprintf( buffer, buffer_size, "%04i-%02i-%02i", + static_cast<int>(_rDate.Year), static_cast<int>(_rDate.Month), static_cast<int>(_rDate.Day) ); + return OUString::createFromAscii( buffer ); + } + + + OUString convertLogArgToString( const css::util::Time& _rTime ) + { + char buffer[ 30 ]; + const size_t buffer_size = sizeof( buffer ); + snprintf( buffer, buffer_size, "%02i:%02i:%02i.%09i", + static_cast<int>(_rTime.Hours), static_cast<int>(_rTime.Minutes), static_cast<int>(_rTime.Seconds), static_cast<int>(_rTime.NanoSeconds) ); + return OUString::createFromAscii( buffer ); + } + + + OUString convertLogArgToString( const DateTime& _rDateTime ) + { + char buffer[ sizeof("-32768-65535-65535 65535:65535:65535.4294967295") ]; + // reserve enough space for hypothetical max length + const size_t buffer_size = sizeof( buffer ); + snprintf( buffer, buffer_size, "%04" SAL_PRIdINT32 "-%02" SAL_PRIuUINT32 "-%02" SAL_PRIuUINT32 " %02" SAL_PRIuUINT32 ":%02" SAL_PRIuUINT32 ":%02" SAL_PRIuUINT32 ".%09" SAL_PRIuUINT32, + static_cast<sal_Int32>(_rDateTime.Year), static_cast<sal_uInt32>(_rDateTime.Month), static_cast<sal_uInt32>(_rDateTime.Day), + static_cast<sal_uInt32>(_rDateTime.Hours), static_cast<sal_uInt32>(_rDateTime.Minutes), static_cast<sal_uInt32>(_rDateTime.Seconds), _rDateTime.NanoSeconds ); + return OUString::createFromAscii( buffer ); + } + + +} // comphelper::log::convert + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/ContextClassLoader.cxx b/connectivity/source/drivers/jdbc/ContextClassLoader.cxx new file mode 100644 index 000000000..50e6bc632 --- /dev/null +++ b/connectivity/source/drivers/jdbc/ContextClassLoader.cxx @@ -0,0 +1,111 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <java/ContextClassLoader.hxx> +#include <java/lang/Object.hxx> + + +namespace connectivity::jdbc +{ + + + using ::com::sun::star::uno::Reference; + using ::com::sun::star::uno::XInterface; + + using ::connectivity::java_lang_Object; + + ContextClassLoaderScope::ContextClassLoaderScope( JNIEnv& environment, const GlobalRef< jobject >& newClassLoader, + const ::comphelper::EventLogger& _rLoggerForErrors, const Reference< XInterface >& _rxErrorContext ) + :m_environment( environment ) + ,m_currentThread( environment ) + ,m_oldContextClassLoader( environment ) + ,m_setContextClassLoaderMethod( nullptr ) + { + if ( !newClassLoader.is() ) + return; + + do // artificial loop for easier flow control + { + + LocalRef< jclass > threadClass( m_environment ); + threadClass.set( m_environment.FindClass( "java/lang/Thread" ) ); + if ( !threadClass.is() ) + break; + + jmethodID currentThreadMethod( m_environment.GetStaticMethodID( + threadClass.get(), "currentThread", "()Ljava/lang/Thread;" ) ); + if ( currentThreadMethod == nullptr ) + break; + + m_currentThread.set( m_environment.CallStaticObjectMethod( threadClass.get(), currentThreadMethod ) ); + if ( !m_currentThread.is() ) + break; + + jmethodID getContextClassLoaderMethod( m_environment.GetMethodID( + threadClass.get(), "getContextClassLoader", "()Ljava/lang/ClassLoader;" ) ); + if ( getContextClassLoaderMethod == nullptr ) + break; + m_oldContextClassLoader.set( m_environment.CallObjectMethod( m_currentThread.get(), getContextClassLoaderMethod ) ); + LocalRef< jthrowable > throwable( m_environment, m_environment.ExceptionOccurred() ); + if ( throwable.is() ) + break; + + m_setContextClassLoaderMethod = m_environment.GetMethodID( + threadClass.get(), "setContextClassLoader", "(Ljava/lang/ClassLoader;)V" ); + if ( m_setContextClassLoaderMethod == nullptr ) + break; + + } + while ( false ); + + if ( !isActive() ) + { + java_lang_Object::ThrowLoggedSQLException( _rLoggerForErrors, &environment, _rxErrorContext ); + return; + } + + // set the new class loader + m_environment.CallObjectMethod( m_currentThread.get(), m_setContextClassLoaderMethod, newClassLoader.get() ); + LocalRef< jthrowable > throwable( m_environment, m_environment.ExceptionOccurred() ); + if ( throwable.is() ) + { + m_currentThread.reset(); + m_setContextClassLoaderMethod = nullptr; + java_lang_Object::ThrowLoggedSQLException( _rLoggerForErrors, &environment, _rxErrorContext ); + } + } + + + ContextClassLoaderScope::~ContextClassLoaderScope() + { + if ( isActive() ) + { + LocalRef< jobject > currentThread( m_currentThread.env(), m_currentThread.release() ); + jmethodID setContextClassLoaderMethod( m_setContextClassLoaderMethod ); + m_setContextClassLoaderMethod = nullptr; + + m_environment.CallObjectMethod( currentThread.get(), setContextClassLoaderMethod, m_oldContextClassLoader.get() ); + m_environment.ExceptionClear(); + } + } + +} // namespace connectivity::jdbc + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/DatabaseMetaData.cxx b/connectivity/source/drivers/jdbc/DatabaseMetaData.cxx new file mode 100644 index 000000000..e1918d11c --- /dev/null +++ b/connectivity/source/drivers/jdbc/DatabaseMetaData.cxx @@ -0,0 +1,1459 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/macros.h> +#include <java/sql/DatabaseMetaData.hxx> +#include <java/sql/Connection.hxx> +#include <java/sql/ResultSet.hxx> +#include <java/sql/SQLException.hxx> +#include <java/tools.hxx> +#include <java/lang/String.hxx> +#include <FDatabaseMetaDataResultSet.hxx> +#include <comphelper/types.hxx> +#include <TPrivilegesResultSet.hxx> +#include <strings.hxx> + +using namespace ::comphelper; + +using namespace connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; + +jclass java_sql_DatabaseMetaData::theClass = nullptr; + +java_sql_DatabaseMetaData::~java_sql_DatabaseMetaData() +{ + SDBThreadAttach::releaseRef(); +} + +jclass java_sql_DatabaseMetaData::getMyClass() const +{ + // the class must be fetched only once, therefore static + if( !theClass ) + theClass = findMyClass("java/sql/DatabaseMetaData"); + return theClass; +} + +java_sql_DatabaseMetaData::java_sql_DatabaseMetaData( JNIEnv * pEnv, jobject myObj, java_sql_Connection& _rConnection ) + :ODatabaseMetaDataBase( &_rConnection,_rConnection.getConnectionInfo() ) + ,java_lang_Object( pEnv, myObj ) + ,m_pConnection( &_rConnection ) + ,m_aLogger( _rConnection.getLogger() ) +{ + SDBThreadAttach::addRef(); +} + + +Reference< XResultSet > java_sql_DatabaseMetaData::impl_getTypeInfo_throw( ) +{ + static jmethodID mID(nullptr); + return impl_callResultSetMethod( "getTypeInfo", mID ); +} + +Reference< XResultSet > SAL_CALL java_sql_DatabaseMetaData::getCatalogs( ) +{ + static jmethodID mID(nullptr); + return impl_callResultSetMethod( "getCatalogs", mID ); +} + +OUString java_sql_DatabaseMetaData::impl_getCatalogSeparator_throw( ) +{ + static jmethodID mID(nullptr); + return impl_callStringMethod( "getCatalogSeparator", mID ); +} + +Reference< XResultSet > SAL_CALL java_sql_DatabaseMetaData::getSchemas( ) +{ + static jmethodID mID(nullptr); + return impl_callResultSetMethod( "getSchemas", mID ); +} + +Reference< XResultSet > SAL_CALL java_sql_DatabaseMetaData::getColumnPrivileges( + const Any& catalog, const OUString& schema, const OUString& table, const OUString& columnNamePattern ) +{ + static jmethodID mID(nullptr); + return impl_callResultSetMethodWithStrings( "getColumnPrivileges", mID, catalog, schema, table, &columnNamePattern ); +} + +Reference< XResultSet > SAL_CALL java_sql_DatabaseMetaData::getColumns( + const Any& catalog, const OUString& schemaPattern, const OUString& tableNamePattern, const OUString& columnNamePattern ) +{ + static jmethodID mID(nullptr); + return impl_callResultSetMethodWithStrings( "getColumns", mID, catalog, schemaPattern, tableNamePattern, &columnNamePattern ); +} + + +Reference< XResultSet > SAL_CALL java_sql_DatabaseMetaData::getTables( + const Any& catalog, const OUString& schemaPattern, const OUString& tableNamePattern, const Sequence< OUString >& _types ) +{ + static const char * const cMethodName = "getTables"; + + m_aLogger.log( LogLevel::FINEST, STR_LOG_META_DATA_METHOD, cMethodName ); + + jobject out(nullptr); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + + { + static const char * const cSignature = "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)Ljava/sql/ResultSet;"; + // execute Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + OSL_VERIFY( !isExceptionOccurred(t.pEnv) ); + jvalue args[4]; + + args[3].l = nullptr; + sal_Int32 typeFilterCount = _types.getLength(); + if ( typeFilterCount ) + { + jobjectArray pObjArray = t.pEnv->NewObjectArray( static_cast<jsize>(typeFilterCount), java_lang_String::st_getMyClass(), nullptr ); + OSL_VERIFY( !isExceptionOccurred( t.pEnv ) ); + const OUString* typeFilter = _types.getConstArray(); + bool bIncludeAllTypes = false; + for ( sal_Int32 i=0; i<typeFilterCount; ++i, ++typeFilter ) + { + if ( *typeFilter == "%" ) + { + bIncludeAllTypes = true; + break; + } + jstring aT = convertwchar_tToJavaString( t.pEnv, *typeFilter ); + t.pEnv->SetObjectArrayElement( pObjArray, static_cast<jsize>(i), aT ); + OSL_VERIFY( !isExceptionOccurred( t.pEnv ) ); + } + + if ( bIncludeAllTypes ) + { + // the SDBC API allows to pass "%" as table type filter, but in JDBC, "all table types" + // is represented by the table type being <null/> + t.pEnv->DeleteLocalRef( pObjArray ); + OSL_VERIFY( !isExceptionOccurred( t.pEnv ) ); + } + else + { + args[3].l = pObjArray; + } + } + // if we are to display "all catalogs", then respect m_aCatalogRestriction + Any aCatalogFilter( catalog ); + if ( !aCatalogFilter.hasValue() ) + aCatalogFilter = m_pConnection->getCatalogRestriction(); + // similar for schema + Any aSchemaFilter; + if ( schemaPattern == "%" ) + aSchemaFilter = m_pConnection->getSchemaRestriction(); + else + aSchemaFilter <<= schemaPattern; + + args[0].l = aCatalogFilter.hasValue() ? convertwchar_tToJavaString( t.pEnv, ::comphelper::getString( aCatalogFilter ) ) : nullptr; + args[1].l = aSchemaFilter.hasValue() ? convertwchar_tToJavaString( t.pEnv, ::comphelper::getString( aSchemaFilter ) ) : nullptr; + args[2].l = convertwchar_tToJavaString(t.pEnv,tableNamePattern); + out = t.pEnv->CallObjectMethod( object, mID, args[0].l, args[1].l,args[2].l,args[3].l); + jthrowable jThrow = t.pEnv->ExceptionOccurred(); + if ( jThrow ) + t.pEnv->ExceptionClear();// we have to clear the exception here because we want to handle it below + if ( aCatalogFilter.hasValue() ) + { + t.pEnv->DeleteLocalRef(static_cast<jstring>(args[0].l)); + OSL_VERIFY( !isExceptionOccurred( t.pEnv ) ); + } + if(args[1].l) + { + t.pEnv->DeleteLocalRef(static_cast<jstring>(args[1].l)); + OSL_VERIFY( !isExceptionOccurred( t.pEnv ) ); + } + if(!tableNamePattern.isEmpty()) + { + t.pEnv->DeleteLocalRef(static_cast<jstring>(args[2].l)); + OSL_VERIFY( !isExceptionOccurred( t.pEnv ) ); + } + //for(INT16 i=0;i<len;i++) + if ( args[3].l ) + { + t.pEnv->DeleteLocalRef( static_cast<jobjectArray>(args[3].l) ); + OSL_VERIFY( !isExceptionOccurred( t.pEnv ) ); + } + + if ( jThrow ) + { + if ( t.pEnv->IsInstanceOf( jThrow,java_sql_SQLException_BASE::st_getMyClass() ) ) + { + java_sql_SQLException_BASE aException( t.pEnv, jThrow ); + SQLException e( aException.getMessage(), + *this, + aException.getSQLState(), + aException.getErrorCode(), + Any() + ); + throw e; + } + } + } + + if ( !out ) + return nullptr; + + m_aLogger.log( LogLevel::FINEST, STR_LOG_META_DATA_SUCCESS, cMethodName ); + return new java_sql_ResultSet( t.pEnv, out, m_aLogger,*m_pConnection); +} + +Reference< XResultSet > SAL_CALL java_sql_DatabaseMetaData::getProcedureColumns( + const Any& catalog, const OUString& schemaPattern, const OUString& procedureNamePattern, const OUString& columnNamePattern ) +{ + static jmethodID mID(nullptr); + return impl_callResultSetMethodWithStrings( "getProcedureColumns", mID, catalog, schemaPattern, procedureNamePattern, &columnNamePattern ); +} + +Reference< XResultSet > SAL_CALL java_sql_DatabaseMetaData::getProcedures( const Any& + catalog, const OUString& schemaPattern, const OUString& procedureNamePattern ) +{ + static jmethodID mID(nullptr); + return impl_callResultSetMethodWithStrings( "getProcedures", mID, catalog, schemaPattern, procedureNamePattern ); +} + +Reference< XResultSet > SAL_CALL java_sql_DatabaseMetaData::getVersionColumns( + const Any& catalog, const OUString& schema, const OUString& table ) +{ + static jmethodID mID(nullptr); + return impl_callResultSetMethodWithStrings( "getVersionColumns", mID, catalog, schema, table ); +} + +sal_Int32 SAL_CALL java_sql_DatabaseMetaData::getMaxBinaryLiteralLength( ) +{ + static jmethodID mID(nullptr); + return impl_callIntMethod_ThrowSQL("getMaxBinaryLiteralLength", mID); +} + +sal_Int32 SAL_CALL java_sql_DatabaseMetaData::getMaxRowSize( ) +{ + static jmethodID mID(nullptr); + return impl_callIntMethod_ThrowSQL("getMaxRowSize", mID); +} + +sal_Int32 SAL_CALL java_sql_DatabaseMetaData::getMaxCatalogNameLength( ) +{ + static jmethodID mID(nullptr); + return impl_callIntMethod_ThrowSQL("getMaxCatalogNameLength", mID); +} + +sal_Int32 SAL_CALL java_sql_DatabaseMetaData::getMaxCharLiteralLength( ) +{ + static jmethodID mID(nullptr); + return impl_callIntMethod_ThrowSQL("getMaxCharLiteralLength", mID); +} + +sal_Int32 SAL_CALL java_sql_DatabaseMetaData::getMaxColumnNameLength( ) +{ + static jmethodID mID(nullptr); + return impl_callIntMethod_ThrowSQL("getMaxColumnNameLength", mID); +} + +sal_Int32 SAL_CALL java_sql_DatabaseMetaData::getMaxColumnsInIndex( ) +{ + static jmethodID mID(nullptr); + return impl_callIntMethod_ThrowSQL("getMaxColumnsInIndex", mID); +} + +sal_Int32 SAL_CALL java_sql_DatabaseMetaData::getMaxCursorNameLength( ) +{ + static jmethodID mID(nullptr); + return impl_callIntMethod_ThrowSQL("getMaxCursorNameLength", mID); +} + +sal_Int32 SAL_CALL java_sql_DatabaseMetaData::getMaxConnections( ) +{ + static jmethodID mID(nullptr); + return impl_callIntMethod_ThrowSQL("getMaxConnections", mID); +} + +sal_Int32 SAL_CALL java_sql_DatabaseMetaData::getMaxColumnsInTable( ) +{ + static jmethodID mID(nullptr); + return impl_callIntMethod_ThrowSQL("getMaxColumnsInTable", mID); +} + +sal_Int32 SAL_CALL java_sql_DatabaseMetaData::getMaxStatementLength( ) +{ + static jmethodID mID(nullptr); + return impl_callIntMethod_ThrowSQL("getMaxStatementLength", mID); +} + +sal_Int32 SAL_CALL java_sql_DatabaseMetaData::getMaxTableNameLength( ) +{ + static jmethodID mID(nullptr); + return impl_callIntMethod_ThrowSQL("getMaxTableNameLength", mID); +} + +sal_Int32 java_sql_DatabaseMetaData::impl_getMaxTablesInSelect_throw( ) +{ + static jmethodID mID(nullptr); + return impl_callIntMethod_ThrowSQL("getMaxTablesInSelect", mID); +} + +Reference< XResultSet > SAL_CALL java_sql_DatabaseMetaData::getExportedKeys( + const Any& catalog, const OUString& schema, const OUString& table ) +{ + static jmethodID mID(nullptr); + return impl_callResultSetMethodWithStrings( "getExportedKeys", mID, catalog, schema, table ); +} + +Reference< XResultSet > SAL_CALL java_sql_DatabaseMetaData::getImportedKeys( + const Any& catalog, const OUString& schema, const OUString& table ) +{ + static jmethodID mID(nullptr); + return impl_callResultSetMethodWithStrings( "getImportedKeys", mID, catalog, schema, table ); +} + +Reference< XResultSet > SAL_CALL java_sql_DatabaseMetaData::getPrimaryKeys( + const Any& catalog, const OUString& schema, const OUString& table ) +{ + static jmethodID mID(nullptr); + return impl_callResultSetMethodWithStrings( "getPrimaryKeys", mID, catalog, schema, table ); +} + +Reference< XResultSet > SAL_CALL java_sql_DatabaseMetaData::getIndexInfo( + const Any& catalog, const OUString& schema, const OUString& table, + sal_Bool unique, sal_Bool approximate ) +{ + static const char * const cMethodName = "getIndexInfo"; + + m_aLogger.log( LogLevel::FINEST, STR_LOG_META_DATA_METHOD, cMethodName ); + + jobject out(nullptr); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + + { + static const char * const cSignature = "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;ZZ)Ljava/sql/ResultSet;"; + // execute Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + jvalue args[5]; + // convert Parameter + args[0].l = catalog.hasValue() ? convertwchar_tToJavaString(t.pEnv,comphelper::getString(catalog)) : nullptr; + args[1].l = schema.toChar() == '%' ? nullptr : convertwchar_tToJavaString(t.pEnv,schema); + args[2].l = convertwchar_tToJavaString(t.pEnv,table); + args[3].z = unique; + args[4].z = approximate; + out = t.pEnv->CallObjectMethod( object, mID, args[0].l,args[1].l,args[2].l,args[3].z,args[4].z ); + + // and clean up + if(catalog.hasValue()) + t.pEnv->DeleteLocalRef(static_cast<jstring>(args[0].l)); + if(args[1].l) + t.pEnv->DeleteLocalRef(static_cast<jstring>(args[1].l)); + if(!table.isEmpty()) + t.pEnv->DeleteLocalRef(static_cast<jstring>(args[2].l)); + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + } + if ( !out ) + return nullptr; + + m_aLogger.log( LogLevel::FINEST, STR_LOG_META_DATA_SUCCESS, cMethodName ); + return new java_sql_ResultSet( t.pEnv, out, m_aLogger,*m_pConnection); +} + +Reference< XResultSet > SAL_CALL java_sql_DatabaseMetaData::getBestRowIdentifier( + const Any& catalog, const OUString& schema, const OUString& table, sal_Int32 scope, + sal_Bool nullable ) +{ + static const char * const cMethodName = "getBestRowIdentifier"; + + m_aLogger.log( LogLevel::FINEST, STR_LOG_META_DATA_METHOD, cMethodName ); + + jobject out(nullptr); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + + { + static const char * const cSignature = "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;IZ)Ljava/sql/ResultSet;"; + // execute Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + jvalue args[3]; + // convert Parameter + args[0].l = catalog.hasValue() ? convertwchar_tToJavaString(t.pEnv,comphelper::getString(catalog)) : nullptr; + args[1].l = schema.toChar() == '%' ? nullptr : convertwchar_tToJavaString(t.pEnv,schema); + args[2].l = convertwchar_tToJavaString(t.pEnv,table); + out = t.pEnv->CallObjectMethod( object, mID, args[0].l,args[1].l,args[2].l,scope,nullable); + + // and cleanup + if(catalog.hasValue()) + t.pEnv->DeleteLocalRef(static_cast<jstring>(args[0].l)); + if(args[1].l) + t.pEnv->DeleteLocalRef(static_cast<jstring>(args[1].l)); + if(!table.isEmpty()) + t.pEnv->DeleteLocalRef(static_cast<jstring>(args[2].l)); + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + } + + if ( !out ) + return nullptr; + + m_aLogger.log( LogLevel::FINEST, STR_LOG_META_DATA_SUCCESS, cMethodName ); + return new java_sql_ResultSet( t.pEnv, out, m_aLogger,*m_pConnection); +} + +Reference< XResultSet > SAL_CALL java_sql_DatabaseMetaData::getTablePrivileges( + const Any& catalog, const OUString& schemaPattern, const OUString& tableNamePattern ) +{ + if ( m_pConnection->isIgnoreDriverPrivilegesEnabled() ) + return new OResultSetPrivileges(this,catalog,schemaPattern,tableNamePattern); + + static jmethodID mID(nullptr); + Reference< XResultSet > xReturn( impl_callResultSetMethodWithStrings( "getTablePrivileges", mID, catalog, schemaPattern, tableNamePattern ) ); + + if ( xReturn.is() ) + { + // we have to check the result columns for the tables privileges + Reference< XResultSetMetaDataSupplier > xMetaSup(xReturn,UNO_QUERY); + if ( xMetaSup.is() ) + { + Reference< XResultSetMetaData> xMeta = xMetaSup->getMetaData(); + if ( xMeta.is() && xMeta->getColumnCount() != 7 ) + { + // here we know that the count of column doesn't match + std::map<sal_Int32,sal_Int32> aColumnMatching; + static const OUStringLiteral sPrivs[] = { + "TABLE_CAT", + "TABLE_SCHEM", + "TABLE_NAME", + "GRANTOR", + "GRANTEE", + "PRIVILEGE", + "IS_GRANTABLE" + }; + + OUString sColumnName; + sal_Int32 nCount = xMeta->getColumnCount(); + for (sal_Int32 i = 1 ; i <= nCount ; ++i) + { + sColumnName = xMeta->getColumnName(i); + for (size_t j = 0 ; j < SAL_N_ELEMENTS(sPrivs); ++j) + { + if ( sPrivs[j] == sColumnName ) + { + aColumnMatching.emplace(i,j+1); + break; + } + } + + } + // fill our own resultset + ODatabaseMetaDataResultSet* pNewPrivRes = new ODatabaseMetaDataResultSet( ODatabaseMetaDataResultSet::eTablePrivileges ); + Reference< XResultSet > xTemp = xReturn; + xReturn = pNewPrivRes; + ODatabaseMetaDataResultSet::ORows aRows; + Reference< XRow > xRow(xTemp,UNO_QUERY); + OUString sValue; + + ODatabaseMetaDataResultSet::ORow aRow(8); + while ( xRow.is() && xTemp->next() ) + { + for (const auto& [nCol, nPriv] : aColumnMatching) + { + sValue = xRow->getString(nCol); + if ( xRow->wasNull() ) + aRow[nPriv] = ODatabaseMetaDataResultSet::getEmptyValue(); + else + aRow[nPriv] = new ORowSetValueDecorator(sValue); + } + + aRows.push_back(aRow); + } + pNewPrivRes->setRows(aRows); + } + } + } + return xReturn; +} + +Reference< XResultSet > SAL_CALL java_sql_DatabaseMetaData::getCrossReference( + const Any& primaryCatalog, const OUString& primarySchema, + const OUString& primaryTable, const Any& foreignCatalog, + const OUString& foreignSchema, const OUString& foreignTable ) +{ + static const char * const cMethodName = "getCrossReference"; + m_aLogger.log( LogLevel::FINEST, STR_LOG_META_DATA_METHOD, cMethodName ); + + jobject out(nullptr); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + { + static const char * const cSignature = "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/sql/ResultSet;"; + // execute Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + jvalue args[6]; + // convert Parameter + args[0].l = primaryCatalog.hasValue() ? convertwchar_tToJavaString(t.pEnv,comphelper::getString(primaryCatalog)) : nullptr; + args[1].l = primarySchema.toChar() == '%' ? nullptr : convertwchar_tToJavaString(t.pEnv,primarySchema); + args[2].l = convertwchar_tToJavaString(t.pEnv,primaryTable); + args[3].l = foreignCatalog.hasValue() ? convertwchar_tToJavaString(t.pEnv,comphelper::getString(foreignCatalog)) : nullptr; + args[4].l = foreignSchema.toChar() == '%' ? nullptr : convertwchar_tToJavaString(t.pEnv,foreignSchema); + args[5].l = convertwchar_tToJavaString(t.pEnv,foreignTable); + out = t.pEnv->CallObjectMethod( object, mID, args[0].l,args[2].l,args[2].l,args[3].l,args[4].l,args[5].l ); + + // and clean up + if(primaryCatalog.hasValue()) + t.pEnv->DeleteLocalRef(static_cast<jstring>(args[0].l)); + if(args[1].l) + t.pEnv->DeleteLocalRef(static_cast<jstring>(args[1].l)); + if(!primaryTable.isEmpty()) + t.pEnv->DeleteLocalRef(static_cast<jstring>(args[2].l)); + if(foreignCatalog.hasValue()) + t.pEnv->DeleteLocalRef(static_cast<jstring>(args[3].l)); + if(args[4].l) + t.pEnv->DeleteLocalRef(static_cast<jstring>(args[4].l)); + if(!foreignTable.isEmpty()) + t.pEnv->DeleteLocalRef(static_cast<jstring>(args[5].l)); + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + } + + if ( !out ) + return nullptr; + + m_aLogger.log( LogLevel::FINEST, STR_LOG_META_DATA_SUCCESS, cMethodName ); + return new java_sql_ResultSet( t.pEnv, out, m_aLogger,*m_pConnection); +} + + +bool java_sql_DatabaseMetaData::impl_callBooleanMethod( const char* _pMethodName, jmethodID& _inout_MethodID ) +{ + m_aLogger.log( LogLevel::FINEST, STR_LOG_META_DATA_METHOD, _pMethodName ); + bool out( java_lang_Object::callBooleanMethod(_pMethodName,_inout_MethodID) ); + m_aLogger.log< const char*, bool>( LogLevel::FINEST, STR_LOG_META_DATA_RESULT, _pMethodName, out ); + return out; +} + + +OUString java_sql_DatabaseMetaData::impl_callStringMethod( const char* _pMethodName, jmethodID& _inout_MethodID ) +{ + m_aLogger.log( LogLevel::FINEST, STR_LOG_META_DATA_METHOD, _pMethodName ); + + const OUString sReturn( callStringMethod(_pMethodName,_inout_MethodID) ); + if ( m_aLogger.isLoggable( LogLevel::FINEST ) ) + { + OUString sLoggedResult( sReturn ); + if ( sLoggedResult.isEmpty() ) + sLoggedResult = "<empty string>"; + m_aLogger.log( LogLevel::FINEST, STR_LOG_META_DATA_RESULT, _pMethodName, sLoggedResult ); + } + + return sReturn; +} + +sal_Int32 java_sql_DatabaseMetaData::impl_callIntMethod_ThrowSQL(const char* _pMethodName, jmethodID& _inout_MethodID) +{ + m_aLogger.log( LogLevel::FINEST, STR_LOG_META_DATA_METHOD, _pMethodName ); + sal_Int32 out( callIntMethod_ThrowSQL(_pMethodName,_inout_MethodID) ); + m_aLogger.log( LogLevel::FINEST, STR_LOG_META_DATA_RESULT, _pMethodName, out ); + return out; +} + +sal_Int32 java_sql_DatabaseMetaData::impl_callIntMethod_ThrowRuntime(const char* _pMethodName, jmethodID& _inout_MethodID) +{ + m_aLogger.log( LogLevel::FINEST, STR_LOG_META_DATA_METHOD, _pMethodName ); + sal_Int32 out( callIntMethod_ThrowRuntime(_pMethodName,_inout_MethodID) ); + m_aLogger.log( LogLevel::FINEST, STR_LOG_META_DATA_RESULT, _pMethodName, out ); + return out; +} + +bool java_sql_DatabaseMetaData::impl_callBooleanMethodWithIntArg( const char* _pMethodName, jmethodID& _inout_MethodID, sal_Int32 _nArgument ) +{ + m_aLogger.log( LogLevel::FINEST, STR_LOG_META_DATA_METHOD_ARG1, _pMethodName, _nArgument ); + + bool out( callBooleanMethodWithIntArg(_pMethodName,_inout_MethodID,_nArgument) ); + + m_aLogger.log< const char*, bool >( LogLevel::FINEST, STR_LOG_META_DATA_RESULT, _pMethodName, out ); + return out; +} + + +Reference< XResultSet > java_sql_DatabaseMetaData::impl_callResultSetMethod( const char* _pMethodName, jmethodID& _inout_MethodID ) +{ + SDBThreadAttach t; + m_aLogger.log( LogLevel::FINEST, STR_LOG_META_DATA_METHOD, _pMethodName ); + jobject out(callResultSetMethod(t.env(),_pMethodName,_inout_MethodID)); + m_aLogger.log( LogLevel::FINEST, STR_LOG_META_DATA_SUCCESS, _pMethodName ); + return new java_sql_ResultSet( t.pEnv, out, m_aLogger,*m_pConnection); +} + + +Reference< XResultSet > java_sql_DatabaseMetaData::impl_callResultSetMethodWithStrings( const char* _pMethodName, jmethodID& _inout_MethodID, + const Any& _rCatalog, const OUString& _rSchemaPattern, const OUString& _rLeastPattern, + const OUString* _pOptionalAdditionalString ) +{ + bool bCatalog = _rCatalog.hasValue(); + OUString sCatalog; + _rCatalog >>= sCatalog; + + bool bSchema = _rSchemaPattern.toChar() != '%'; + + // log the call + if ( m_aLogger.isLoggable( LogLevel::FINEST ) ) + { + OUString sCatalogLog = bCatalog ? sCatalog : OUString( "null" ); + OUString sSchemaLog = bSchema ? _rSchemaPattern : OUString( "null" ); + if ( _pOptionalAdditionalString ) + m_aLogger.log( LogLevel::FINEST, STR_LOG_META_DATA_METHOD_ARG4, _pMethodName, sCatalogLog, sSchemaLog, _rLeastPattern, *_pOptionalAdditionalString ); + else + m_aLogger.log( LogLevel::FINEST, STR_LOG_META_DATA_METHOD_ARG3, _pMethodName, sCatalogLog, sSchemaLog, _rLeastPattern ); + } + + jobject out(nullptr); + + SDBThreadAttach t; + OSL_ENSURE( t.pEnv, "java_sql_DatabaseMetaData::impl_callResultSetMethodWithStrings: no Java environment anymore!" ); + + { + const char* pSignature = _pOptionalAdditionalString + ? "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/sql/ResultSet;" + : "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)Ljava/sql/ResultSet;"; + // obtain method ID + obtainMethodId_throwSQL(t.pEnv, _pMethodName,pSignature, _inout_MethodID); + + // call method + + { + jvalue args[4]; + // convert parameters + args[0].l = bCatalog ? convertwchar_tToJavaString( t.pEnv, sCatalog ) : nullptr; + args[1].l = bSchema ? convertwchar_tToJavaString( t.pEnv, _rSchemaPattern ) : nullptr; + args[2].l = convertwchar_tToJavaString( t.pEnv, _rLeastPattern ); + args[3].l = _pOptionalAdditionalString ? convertwchar_tToJavaString( t.pEnv, *_pOptionalAdditionalString ) : nullptr; + + // actually do the call + if ( _pOptionalAdditionalString ) + out = t.pEnv->CallObjectMethod( object, _inout_MethodID, args[0].l, args[1].l, args[2].l, args[3].l ); + else + out = t.pEnv->CallObjectMethod( object, _inout_MethodID, args[0].l, args[1].l, args[2].l ); + + // clean up + if ( args[0].l ) + t.pEnv->DeleteLocalRef( static_cast<jstring>(args[0].l) ); + if ( args[1].l ) + t.pEnv->DeleteLocalRef( static_cast<jstring>(args[1].l) ); + if ( args[2].l ) + t.pEnv->DeleteLocalRef( static_cast<jstring>(args[2].l) ); + if ( args[3].l ) + t.pEnv->DeleteLocalRef( static_cast<jstring>(args[3].l) ); + + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + } + } + + if ( !out ) + return nullptr; + + m_aLogger.log( LogLevel::FINEST, STR_LOG_META_DATA_SUCCESS, _pMethodName ); + return new java_sql_ResultSet( t.pEnv, out, m_aLogger,*m_pConnection); +} + + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::doesMaxRowSizeIncludeBlobs( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "doesMaxRowSizeIncludeBlobs", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::storesLowerCaseQuotedIdentifiers( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "storesLowerCaseQuotedIdentifiers", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::storesLowerCaseIdentifiers( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "storesLowerCaseIdentifiers", mID ); +} + +bool java_sql_DatabaseMetaData::impl_storesMixedCaseQuotedIdentifiers_throw( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "storesMixedCaseQuotedIdentifiers", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::storesMixedCaseIdentifiers( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "storesMixedCaseIdentifiers", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::storesUpperCaseQuotedIdentifiers( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "storesUpperCaseQuotedIdentifiers", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::storesUpperCaseIdentifiers( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "storesUpperCaseIdentifiers", mID ); +} + +bool java_sql_DatabaseMetaData::impl_supportsAlterTableWithAddColumn_throw( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsAlterTableWithAddColumn", mID ); +} + +bool java_sql_DatabaseMetaData::impl_supportsAlterTableWithDropColumn_throw( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsAlterTableWithDropColumn", mID ); +} + +sal_Int32 SAL_CALL java_sql_DatabaseMetaData::getMaxIndexLength( ) +{ + static jmethodID mID(nullptr); + return impl_callIntMethod_ThrowSQL("getMaxIndexLength", mID); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsNonNullableColumns( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsNonNullableColumns", mID ); +} + +OUString SAL_CALL java_sql_DatabaseMetaData::getCatalogTerm( ) +{ + static jmethodID mID(nullptr); + return impl_callStringMethod( "getCatalogTerm", mID ); +} + +OUString java_sql_DatabaseMetaData::impl_getIdentifierQuoteString_throw( ) +{ + static jmethodID mID(nullptr); + return impl_callStringMethod( "getIdentifierQuoteString", mID ); +} + +OUString SAL_CALL java_sql_DatabaseMetaData::getExtraNameCharacters( ) +{ + static jmethodID mID(nullptr); + return impl_callStringMethod( "getExtraNameCharacters", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsDifferentTableCorrelationNames( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsDifferentTableCorrelationNames", mID ); +} + +bool java_sql_DatabaseMetaData::impl_isCatalogAtStart_throw( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "isCatalogAtStart", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::dataDefinitionIgnoredInTransactions( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "dataDefinitionIgnoredInTransactions", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::dataDefinitionCausesTransactionCommit( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "dataDefinitionCausesTransactionCommit", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsDataManipulationTransactionsOnly( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsDataManipulationTransactionsOnly", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsDataDefinitionAndDataManipulationTransactions( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsDataDefinitionAndDataManipulationTransactions", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsPositionedDelete( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsPositionedDelete", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsPositionedUpdate( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsPositionedUpdate", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsOpenStatementsAcrossRollback( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsOpenStatementsAcrossRollback", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsOpenStatementsAcrossCommit( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsOpenStatementsAcrossCommit", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsOpenCursorsAcrossCommit( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsOpenCursorsAcrossCommit", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsOpenCursorsAcrossRollback( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsOpenCursorsAcrossRollback", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsTransactionIsolationLevel( sal_Int32 level ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethodWithIntArg( "supportsTransactionIsolationLevel", mID, level ); +} + +bool java_sql_DatabaseMetaData::impl_supportsSchemasInDataManipulation_throw( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsSchemasInDataManipulation", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsANSI92FullSQL( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsANSI92FullSQL", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsANSI92EntryLevelSQL( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsANSI92EntryLevelSQL", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsIntegrityEnhancementFacility( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsIntegrityEnhancementFacility", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsSchemasInIndexDefinitions( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsSchemasInIndexDefinitions", mID ); +} + +bool java_sql_DatabaseMetaData::impl_supportsSchemasInTableDefinitions_throw( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsSchemasInTableDefinitions", mID ); +} + +bool java_sql_DatabaseMetaData::impl_supportsCatalogsInTableDefinitions_throw( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsCatalogsInTableDefinitions", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsCatalogsInIndexDefinitions( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsCatalogsInIndexDefinitions", mID ); +} + +bool java_sql_DatabaseMetaData::impl_supportsCatalogsInDataManipulation_throw( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsCatalogsInDataManipulation", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsOuterJoins( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsOuterJoins", mID ); +} + +Reference< XResultSet > SAL_CALL java_sql_DatabaseMetaData::getTableTypes( ) +{ + static jmethodID mID(nullptr); + return impl_callResultSetMethod( "getTableTypes", mID ); +} + +sal_Int32 java_sql_DatabaseMetaData::impl_getMaxStatements_throw( ) +{ + static jmethodID mID(nullptr); + return impl_callIntMethod_ThrowSQL("getMaxStatements", mID); +} + +sal_Int32 SAL_CALL java_sql_DatabaseMetaData::getMaxProcedureNameLength( ) +{ + static jmethodID mID(nullptr); + return impl_callIntMethod_ThrowSQL("getMaxProcedureNameLength", mID); +} + +sal_Int32 SAL_CALL java_sql_DatabaseMetaData::getMaxSchemaNameLength( ) +{ + static jmethodID mID(nullptr); + return impl_callIntMethod_ThrowSQL("getMaxSchemaNameLength", mID); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsTransactions( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsTransactions", mID ); +} + + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::allProceduresAreCallable( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "allProceduresAreCallable", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsStoredProcedures( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsStoredProcedures", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsSelectForUpdate( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsSelectForUpdate", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::allTablesAreSelectable( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "allTablesAreSelectable", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::isReadOnly( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "isReadOnly", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::usesLocalFiles( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "usesLocalFiles", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::usesLocalFilePerTable( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "usesLocalFilePerTable", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsTypeConversion( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsTypeConversion", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::nullPlusNonNullIsNull( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "nullPlusNonNullIsNull", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsColumnAliasing( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsColumnAliasing", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsTableCorrelationNames( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsTableCorrelationNames", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsConvert( sal_Int32 fromType, sal_Int32 toType ) +{ + static const char* const pMethodName = "supportsConvert"; + m_aLogger.log( LogLevel::FINEST, STR_LOG_META_DATA_METHOD_ARG2, pMethodName, fromType, toType ); + + bool out( false ); + SDBThreadAttach t; + + { + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, pMethodName,"(II)Z", mID); + out = t.pEnv->CallBooleanMethod( object, mID, fromType, toType ); + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + } + + m_aLogger.log< const char*, bool >( LogLevel::FINEST, STR_LOG_META_DATA_RESULT, pMethodName, out ); + return out; +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsExpressionsInOrderBy( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsExpressionsInOrderBy", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsGroupBy( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsGroupBy", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsGroupByBeyondSelect( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsGroupByBeyondSelect", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsGroupByUnrelated( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsGroupByUnrelated", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsMultipleTransactions( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsMultipleTransactions", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsMultipleResultSets( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsMultipleResultSets", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsLikeEscapeClause( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsLikeEscapeClause", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsOrderByUnrelated( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsOrderByUnrelated", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsUnion( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsUnion", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsUnionAll( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsUnionAll", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsMixedCaseIdentifiers( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsMixedCaseIdentifiers", mID ); +} + +bool java_sql_DatabaseMetaData::impl_supportsMixedCaseQuotedIdentifiers_throw( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsMixedCaseQuotedIdentifiers", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::nullsAreSortedAtEnd( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "nullsAreSortedAtEnd", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::nullsAreSortedAtStart( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "nullsAreSortedAtStart", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::nullsAreSortedHigh( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "nullsAreSortedHigh", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::nullsAreSortedLow( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "nullsAreSortedLow", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsSchemasInProcedureCalls( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsSchemasInProcedureCalls", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsSchemasInPrivilegeDefinitions( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsSchemasInPrivilegeDefinitions", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsCatalogsInProcedureCalls( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsCatalogsInProcedureCalls", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsCatalogsInPrivilegeDefinitions( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsCatalogsInPrivilegeDefinitions", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsCorrelatedSubqueries( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsCorrelatedSubqueries", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsSubqueriesInComparisons( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsSubqueriesInComparisons", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsSubqueriesInExists( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsSubqueriesInExists", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsSubqueriesInIns( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsSubqueriesInIns", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsSubqueriesInQuantifieds( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsSubqueriesInQuantifieds", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsANSI92IntermediateSQL( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsANSI92IntermediateSQL", mID ); +} + +OUString SAL_CALL java_sql_DatabaseMetaData::getURL( ) +{ + OUString sURL = m_pConnection->getURL(); + if ( sURL.isEmpty() ) + { + static jmethodID mID(nullptr); + sURL = impl_callStringMethod( "getURL", mID ); + } + return sURL; +} + +OUString SAL_CALL java_sql_DatabaseMetaData::getUserName( ) +{ + static jmethodID mID(nullptr); + return impl_callStringMethod( "getUserName", mID ); +} + +OUString SAL_CALL java_sql_DatabaseMetaData::getDriverName( ) +{ + static jmethodID mID(nullptr); + return impl_callStringMethod( "getDriverName", mID ); +} + +OUString SAL_CALL java_sql_DatabaseMetaData::getDriverVersion( ) +{ + static jmethodID mID(nullptr); + return impl_callStringMethod( "getDriverVersion", mID ); +} + +OUString SAL_CALL java_sql_DatabaseMetaData::getDatabaseProductVersion( ) +{ + static jmethodID mID(nullptr); + return impl_callStringMethod( "getDatabaseProductVersion", mID ); +} + +OUString SAL_CALL java_sql_DatabaseMetaData::getDatabaseProductName( ) +{ + static jmethodID mID(nullptr); + return impl_callStringMethod( "getDatabaseProductName", mID ); +} + +OUString SAL_CALL java_sql_DatabaseMetaData::getProcedureTerm( ) +{ + static jmethodID mID(nullptr); + return impl_callStringMethod( "getProcedureTerm", mID ); +} + +OUString SAL_CALL java_sql_DatabaseMetaData::getSchemaTerm( ) +{ + static jmethodID mID(nullptr); + return impl_callStringMethod( "getSchemaTerm", mID ); +} + +sal_Int32 SAL_CALL java_sql_DatabaseMetaData::getDriverMajorVersion( ) +{ + static jmethodID mID(nullptr); + return impl_callIntMethod_ThrowRuntime("getDriverMajorVersion", mID); +} + +sal_Int32 SAL_CALL java_sql_DatabaseMetaData::getDefaultTransactionIsolation( ) +{ + static jmethodID mID(nullptr); + return impl_callIntMethod_ThrowSQL("getDefaultTransactionIsolation", mID); +} + +sal_Int32 SAL_CALL java_sql_DatabaseMetaData::getDriverMinorVersion( ) +{ + static jmethodID mID(nullptr); + return impl_callIntMethod_ThrowRuntime("getDriverMinorVersion", mID); +} + +OUString SAL_CALL java_sql_DatabaseMetaData::getSQLKeywords( ) +{ + static jmethodID mID(nullptr); + return impl_callStringMethod( "getSQLKeywords", mID ); +} + +OUString SAL_CALL java_sql_DatabaseMetaData::getSearchStringEscape( ) +{ + static jmethodID mID(nullptr); + return impl_callStringMethod( "getSearchStringEscape", mID ); +} + +OUString SAL_CALL java_sql_DatabaseMetaData::getStringFunctions( ) +{ + static jmethodID mID(nullptr); + return impl_callStringMethod( "getStringFunctions", mID ); +} + +OUString SAL_CALL java_sql_DatabaseMetaData::getTimeDateFunctions( ) +{ + static jmethodID mID(nullptr); + return impl_callStringMethod( "getTimeDateFunctions", mID ); +} + +OUString SAL_CALL java_sql_DatabaseMetaData::getSystemFunctions( ) +{ + static jmethodID mID(nullptr); + return impl_callStringMethod( "getSystemFunctions", mID ); +} + +OUString SAL_CALL java_sql_DatabaseMetaData::getNumericFunctions( ) +{ + static jmethodID mID(nullptr); + return impl_callStringMethod( "getNumericFunctions", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsExtendedSQLGrammar( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsExtendedSQLGrammar", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsCoreSQLGrammar( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsCoreSQLGrammar", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsMinimumSQLGrammar( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsMinimumSQLGrammar", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsFullOuterJoins( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsFullOuterJoins", mID ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsLimitedOuterJoins( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsLimitedOuterJoins", mID ); +} + +sal_Int32 SAL_CALL java_sql_DatabaseMetaData::getMaxColumnsInGroupBy( ) +{ + static jmethodID mID(nullptr); + return impl_callIntMethod_ThrowSQL("getMaxColumnsInGroupBy", mID); +} + +sal_Int32 SAL_CALL java_sql_DatabaseMetaData::getMaxColumnsInOrderBy( ) +{ + static jmethodID mID(nullptr); + return impl_callIntMethod_ThrowSQL("getMaxColumnsInOrderBy", mID); +} + +sal_Int32 SAL_CALL java_sql_DatabaseMetaData::getMaxColumnsInSelect( ) +{ + static jmethodID mID(nullptr); + return impl_callIntMethod_ThrowSQL("getMaxColumnsInSelect", mID); +} + +sal_Int32 SAL_CALL java_sql_DatabaseMetaData::getMaxUserNameLength( ) +{ + static jmethodID mID(nullptr); + return impl_callIntMethod_ThrowSQL("getMaxUserNameLength", mID); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsResultSetType( sal_Int32 setType ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethodWithIntArg( "supportsResultSetType", mID, setType ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsResultSetConcurrency( sal_Int32 setType, sal_Int32 concurrency ) +{ + static const char* const pMethodName = "supportsResultSetConcurrency"; + m_aLogger.log( LogLevel::FINEST, STR_LOG_META_DATA_METHOD_ARG2, pMethodName, setType, concurrency ); + + bool out( false ); + SDBThreadAttach t; + + { + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, pMethodName,"(II)Z", mID); + out = t.pEnv->CallBooleanMethod( object, mID, setType, concurrency); + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + } + + m_aLogger.log< const char*, bool >( LogLevel::FINEST, STR_LOG_META_DATA_RESULT, pMethodName, out ); + return out; +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::ownUpdatesAreVisible( sal_Int32 setType ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethodWithIntArg( "ownUpdatesAreVisible", mID, setType ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::ownDeletesAreVisible( sal_Int32 setType ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethodWithIntArg( "ownDeletesAreVisible", mID, setType ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::ownInsertsAreVisible( sal_Int32 setType ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethodWithIntArg( "ownInsertsAreVisible", mID, setType ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::othersUpdatesAreVisible( sal_Int32 setType ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethodWithIntArg( "othersUpdatesAreVisible", mID, setType ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::othersDeletesAreVisible( sal_Int32 setType ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethodWithIntArg( "othersDeletesAreVisible", mID, setType ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::othersInsertsAreVisible( sal_Int32 setType ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethodWithIntArg( "othersInsertsAreVisible", mID, setType ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::updatesAreDetected( sal_Int32 setType ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethodWithIntArg( "updatesAreDetected", mID, setType ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::deletesAreDetected( sal_Int32 setType ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethodWithIntArg( "deletesAreDetected", mID, setType ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::insertsAreDetected( sal_Int32 setType ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethodWithIntArg( "insertsAreDetected", mID, setType ); +} + +sal_Bool SAL_CALL java_sql_DatabaseMetaData::supportsBatchUpdates( ) +{ + static jmethodID mID(nullptr); + return impl_callBooleanMethod( "supportsBatchUpdates", mID ); +} + +Reference< XResultSet > SAL_CALL java_sql_DatabaseMetaData::getUDTs( + const Any& catalog, const OUString& schemaPattern, const OUString& typeNamePattern, + const Sequence< sal_Int32 >& types ) +{ + jobject out(nullptr); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + { + + + static const char * const cSignature = "(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;[I)Ljava/sql/ResultSet;"; + static const char * const cMethodName = "getUDTs"; + // dismiss Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + { + jvalue args[4]; + // initialize temporary Variable + args[0].l = catalog.hasValue() ? convertwchar_tToJavaString(t.pEnv,comphelper::getString(catalog)) : nullptr; + args[1].l = schemaPattern.toChar() == '%' ? nullptr : convertwchar_tToJavaString(t.pEnv,schemaPattern); + args[2].l = convertwchar_tToJavaString(t.pEnv,typeNamePattern); + jintArray pArray = t.pEnv->NewIntArray(types.getLength()); + jint * typesData = reinterpret_cast<jint *>( + const_cast<sal_Int32 *>(types.getConstArray())); + // 4th param of Set*ArrayRegion changed from pointer to non-const to + // pointer to const between <http://docs.oracle.com/javase/6/docs/ + // technotes/guides/jni/spec/functions.html#wp22933> and + // <http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/ + // functions.html#wp22933>; work around that difference in a way + // that doesn't trigger loplugin:redundantcast + t.pEnv->SetIntArrayRegion(pArray,0,types.getLength(),typesData); + args[3].l = pArray; + + out = t.pEnv->CallObjectMethod( object, mID, args[0].l, args[1].l,args[2].l,args[3].l); + + if(catalog.hasValue()) + t.pEnv->DeleteLocalRef(static_cast<jstring>(args[0].l)); + if(!schemaPattern.isEmpty()) + t.pEnv->DeleteLocalRef(static_cast<jstring>(args[1].l)); + if(!typeNamePattern.isEmpty()) + t.pEnv->DeleteLocalRef(static_cast<jstring>(args[2].l)); + if(args[3].l) + t.pEnv->DeleteLocalRef(static_cast<jintArray>(args[3].l)); + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + } + } + + return out ? new java_sql_ResultSet( t.pEnv, out, m_aLogger,*m_pConnection ) : nullptr; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/Date.cxx b/connectivity/source/drivers/jdbc/Date.cxx new file mode 100644 index 000000000..8adaf455a --- /dev/null +++ b/connectivity/source/drivers/jdbc/Date.cxx @@ -0,0 +1,41 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <java/util/Date.hxx> + +using namespace connectivity; + +//************ Class: java.util.Date + + +jclass java_util_Date::theClass = nullptr; + +java_util_Date::~java_util_Date() +{} + +jclass java_util_Date::getMyClass() const +{ + // the class must be fetched only once, therefore static + if( !theClass ) + theClass = findMyClass("java/util/Date"); + return theClass; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/DriverPropertyInfo.cxx b/connectivity/source/drivers/jdbc/DriverPropertyInfo.cxx new file mode 100644 index 000000000..9c33eeb60 --- /dev/null +++ b/connectivity/source/drivers/jdbc/DriverPropertyInfo.cxx @@ -0,0 +1,44 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <java/sql/DriverPropertyInfo.hxx> + +using namespace connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::lang; + + +//************ Class: java.sql.Driver + + +jclass java_sql_DriverPropertyInfo::theClass = nullptr; + +java_sql_DriverPropertyInfo::~java_sql_DriverPropertyInfo() +{} + +jclass java_sql_DriverPropertyInfo::getMyClass() const +{ + // the class must be fetched only once, therefore static + if( !theClass ) + theClass = findMyClass("java/sql/DriverPropertyInfo"); + return theClass; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/Exception.cxx b/connectivity/source/drivers/jdbc/Exception.cxx new file mode 100644 index 000000000..2fdef4ee8 --- /dev/null +++ b/connectivity/source/drivers/jdbc/Exception.cxx @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <java/lang/Exception.hxx> +using namespace connectivity; + +//************ Class: java.lang.Exception + + +jclass java_lang_Exception::theClass = nullptr; + +java_lang_Exception::~java_lang_Exception() +{} + +jclass java_lang_Exception::getMyClass() const +{ + // the class must be fetched only once, therefore static + if( !theClass ) + theClass = findMyClass("java/lang/Exception"); + return theClass; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/InputStream.cxx b/connectivity/source/drivers/jdbc/InputStream.cxx new file mode 100644 index 000000000..c384760b3 --- /dev/null +++ b/connectivity/source/drivers/jdbc/InputStream.cxx @@ -0,0 +1,113 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> +#include <sal/log.hxx> + +#include <com/sun/star/io/BufferSizeExceededException.hpp> +#include <java/io/InputStream.hxx> +#include <osl/diagnose.h> + +#include <string.h> + +using namespace connectivity; + +#if OSL_DEBUG_LEVEL > 0 +#define THROW_WHERE SAL_WHERE +#else +#define THROW_WHERE "" +#endif + + +//************ Class: java.io.InputStream + + +jclass java_io_InputStream::theClass = nullptr; +java_io_InputStream::java_io_InputStream( JNIEnv * pEnv, jobject myObj ) + : java_lang_Object( pEnv, myObj ) +{ + SDBThreadAttach::addRef(); +} +java_io_InputStream::~java_io_InputStream() +{ + SDBThreadAttach::releaseRef(); +} + +jclass java_io_InputStream::getMyClass() const +{ + // the class must be fetched only once, therefore static + if( !theClass ) + theClass = findMyClass("java/io/InputStream"); + return theClass; +} + + +sal_Int32 SAL_CALL java_io_InputStream::readSomeBytes( css::uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) +{ + return readBytes(aData,nMaxBytesToRead); +} + +void SAL_CALL java_io_InputStream::skipBytes( sal_Int32 nBytesToSkip ) +{ + static jmethodID mID(nullptr); + callIntMethodWithIntArg_ThrowRuntime("skip",mID,nBytesToSkip); +} + +sal_Int32 SAL_CALL java_io_InputStream::available( ) +{ + static jmethodID mID(nullptr); + return callIntMethod_ThrowRuntime("available", mID); +} + +void SAL_CALL java_io_InputStream::closeInput( ) +{ + static jmethodID mID(nullptr); + callVoidMethod_ThrowRuntime("close",mID); +} + +sal_Int32 SAL_CALL java_io_InputStream::readBytes( css::uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) +{ + if (nBytesToRead < 0) + throw css::io::BufferSizeExceededException( THROW_WHERE, *this ); + + jint out(0); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + + { + jbyteArray pByteArray = t.pEnv->NewByteArray(nBytesToRead); + static const char * const cSignature = "([BII)I"; + static const char * const cMethodName = "read"; + // execute Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwRuntime(t.pEnv, cMethodName,cSignature, mID); + out = t.pEnv->CallIntMethod( object, mID, pByteArray, 0, nBytesToRead ); + if ( !out ) + ThrowRuntimeException(t.pEnv,*this); + if(out > 0) + { + jboolean p = false; + aData.realloc ( out ); + memcpy(aData.getArray(),t.pEnv->GetByteArrayElements(pByteArray,&p),out); + } + t.pEnv->DeleteLocalRef(pByteArray); + } //t.pEnv + return out; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/JBigDecimal.cxx b/connectivity/source/drivers/jdbc/JBigDecimal.cxx new file mode 100644 index 000000000..7cbcd6486 --- /dev/null +++ b/connectivity/source/drivers/jdbc/JBigDecimal.cxx @@ -0,0 +1,79 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <java/math/BigDecimal.hxx> +#include <java/tools.hxx> +using namespace connectivity; + +//************ Class: java.lang.Boolean + + +jclass java_math_BigDecimal::theClass = nullptr; + +java_math_BigDecimal::~java_math_BigDecimal() +{} + +jclass java_math_BigDecimal::getMyClass() const +{ + // the class must be fetched only once, therefore static + if( !theClass ) + theClass = findMyClass("java/math/BigDecimal"); + return theClass; +} + +java_math_BigDecimal::java_math_BigDecimal( const OUString& _par0 ): java_lang_Object( nullptr, nullptr ) +{ + SDBThreadAttach t; + if( !t.pEnv ) + return; + // Java-Call for the Constructor + // initialize temporary Variable + static const char * const cSignature = "(Ljava/lang/String;)V"; + jobject tempObj; + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, "<init>",cSignature, mID); + + jstring str = convertwchar_tToJavaString(t.pEnv,_par0.replace(',','.')); + tempObj = t.pEnv->NewObject( getMyClass(), mID, str ); + t.pEnv->DeleteLocalRef(str); + saveRef( t.pEnv, tempObj ); + t.pEnv->DeleteLocalRef( tempObj ); + ThrowSQLException( t.pEnv, nullptr ); + // and cleanup +} + +java_math_BigDecimal::java_math_BigDecimal( const double& _par0 ): java_lang_Object( nullptr, nullptr ) +{ + SDBThreadAttach t; + if( !t.pEnv ) + return; + // Java-Call for the Constructor + // initialize temporary Variable + static const char * const cSignature = "(D)V"; + jobject tempObj; + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, "<init>",cSignature, mID); + tempObj = t.pEnv->NewObject( getMyClass(), mID, _par0 ); + saveRef( t.pEnv, tempObj ); + t.pEnv->DeleteLocalRef( tempObj ); + ThrowSQLException( t.pEnv, nullptr ); + // and cleanup +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/JConnection.cxx b/connectivity/source/drivers/jdbc/JConnection.cxx new file mode 100644 index 000000000..1d33f2941 --- /dev/null +++ b/connectivity/source/drivers/jdbc/JConnection.cxx @@ -0,0 +1,804 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <sal/config.h> + +#include <java/sql/Connection.hxx> +#include <java/lang/Class.hxx> +#include <java/tools.hxx> +#include <java/ContextClassLoader.hxx> +#include <java/sql/DatabaseMetaData.hxx> +#include <java/sql/JStatement.hxx> +#include <java/sql/Driver.hxx> +#include <java/sql/PreparedStatement.hxx> +#include <java/sql/CallableStatement.hxx> +#include <java/sql/SQLWarning.hxx> +#include <com/sun/star/sdbc/SQLWarning.hpp> +#include <com/sun/star/beans/NamedValue.hpp> +#include <connectivity/dbexception.hxx> +#include <java/util/Property.hxx> +#include <java/LocalRef.hxx> +#include <com/sun/star/uno/XComponentContext.hpp> +#include <jvmaccess/classpath.hxx> +#include <comphelper/namedvaluecollection.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <jni.h> +#include <strings.hrc> +#include <unotools/confignode.hxx> +#include <strings.hxx> + +#include <vector> +#include <memory> + +using namespace connectivity; +using namespace connectivity::jdbc; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; + +namespace { + +struct ClassMapEntry { + ClassMapEntry( + OUString const & theClassPath, OUString const & theClassName): + classPath(theClassPath), className(theClassName), classLoader(nullptr), + classObject(nullptr) {} + + OUString classPath; + OUString className; + jweak classLoader; + jweak classObject; +}; + +typedef std::vector< ClassMapEntry > ClassMap; + +struct ClassMapData { + osl::Mutex mutex; + + ClassMap map; +}; + +template < typename T > +bool getLocalFromWeakRef( jweak& _weak, LocalRef< T >& _inout_local ) +{ + _inout_local.set( static_cast< T >( _inout_local.env().NewLocalRef( _weak ) ) ); + + if ( !_inout_local.is() ) + { + if ( _inout_local.env().ExceptionCheck()) + { + return false; + } + else if ( _weak != nullptr ) + { + _inout_local.env().DeleteWeakGlobalRef( _weak ); + _weak = nullptr; + } + } + return true; +} + +// Load a class. A map from pairs of (classPath, name) to pairs of weak Java +// references to (ClassLoader, Class) is maintained, so that a class is only +// loaded once. +// +// It may happen that the weak reference to the ClassLoader becomes null while +// the reference to the Class remains non-null (in case the Class was actually +// loaded by some parent of the ClassLoader), in which case the ClassLoader is +// resurrected (which cannot cause any classes to be loaded multiple times, as +// the ClassLoader is no longer reachable, so no classes it has ever loaded are +// still reachable). +// +// Similarly, it may happen that the weak reference to the Class becomes null +// while the reference to the ClassLoader remains non-null, in which case the +// Class is simply re-loaded. +// +// This code is close to the implementation of jvmaccess::ClassPath::loadClass +// in jvmaccess/classpath.hxx, but not close enough to avoid the duplication. +// +// If false is returned, a (still pending) JNI exception occurred. +bool loadClass( + Reference< XComponentContext > const & context, JNIEnv& environment, + OUString const & classPath, OUString const & name, + LocalRef< jobject > * classLoaderPtr, LocalRef< jclass > * classPtr) +{ + OSL_ASSERT(classLoaderPtr != nullptr); + // For any jweak entries still present in the map upon destruction, + // DeleteWeakGlobalRef is not called (which is a leak): + static ClassMapData classMapData; + osl::MutexGuard g(classMapData.mutex); + ClassMap::iterator i(classMapData.map.begin()); + LocalRef< jobject > cloader(environment); + LocalRef< jclass > cl(environment); + // Prune dangling weak references from the list while searching for a match, + // so that the list cannot grow unbounded: + for (; i != classMapData.map.end();) + { + LocalRef< jobject > classLoader( environment ); + if ( !getLocalFromWeakRef( i->classLoader, classLoader ) ) + return false; + + LocalRef< jclass > classObject( environment ); + if ( !getLocalFromWeakRef( i->classObject, classObject ) ) + return false; + + if ( !classLoader.is() && !classObject.is() ) + { + i = classMapData.map.erase(i); + } + else if ( i->classPath == classPath && i->className == name ) + { + cloader.set( classLoader.release() ); + cl.set( classObject.release() ); + break; + } + else + { + ++i; + } + } + if ( !cloader.is() || !cl.is() ) + { + if ( i == classMapData.map.end() ) + { + // Push a new ClassMapEntry (which can potentially fail) before + // loading the class, so that it never happens that a class is + // loaded but not added to the map (which could have effects on the + // JVM that are not easily undone). If the pushed ClassMapEntry is + // not used after all (return false, etc.) it will be pruned on next + // call because its classLoader/classObject are null: + classMapData.map.push_back( ClassMapEntry( classPath, name ) ); + i = std::prev(classMapData.map.end()); + } + + LocalRef< jclass > clClass( environment ); + clClass.set( environment.FindClass( "java/net/URLClassLoader" ) ); + if ( !clClass.is() ) + return false; + + jweak wcloader = nullptr; + if (!cloader.is()) + { + jmethodID ctorLoader( environment.GetMethodID( clClass.get(), "<init>", "([Ljava/net/URL;)V" ) ); + if (ctorLoader == nullptr) + return false; + + LocalRef< jobjectArray > arr( environment ); + arr.set( jvmaccess::ClassPath::translateToUrls( context, &environment, classPath ) ); + if ( !arr.is() ) + return false; + + jvalue arg; + arg.l = arr.get(); + cloader.set( environment.NewObjectA( clClass.get(), ctorLoader, &arg ) ); + if ( !cloader.is() ) + return false; + + wcloader = environment.NewWeakGlobalRef( cloader.get() ); + if ( wcloader == nullptr ) + return false; + } + + jweak wcl = nullptr; + if ( !cl.is() ) + { + jmethodID methLoadClass( environment.GetMethodID( clClass.get(), "loadClass", "(Ljava/lang/String;)Ljava/lang/Class;" ) ); + if ( methLoadClass == nullptr ) + return false; + + LocalRef< jstring > str( environment ); + str.set( convertwchar_tToJavaString( &environment, name ) ); + if ( !str.is() ) + return false; + + jvalue arg; + arg.l = str.get(); + cl.set( static_cast< jclass >( environment.CallObjectMethodA( cloader.get(), methLoadClass, &arg ) ) ); + if ( !cl.is() ) + return false; + + wcl = environment.NewWeakGlobalRef( cl.get() ); + if ( wcl == nullptr ) + return false; + } + + if ( wcloader != nullptr) + { + i->classLoader = wcloader; + } + if ( wcl != nullptr ) + { + i->classObject = wcl; + } + } + + classLoaderPtr->set( cloader.release() ); + classPtr->set( cl.release() ); + return true; +} + +} + + +IMPLEMENT_SERVICE_INFO(java_sql_Connection,"com.sun.star.sdbcx.JConnection","com.sun.star.sdbc.Connection"); + + +//************ Class: java.sql.Connection + +jclass java_sql_Connection::theClass = nullptr; + +java_sql_Connection::java_sql_Connection( const java_sql_Driver& _rDriver ) + :java_lang_Object() + ,m_xContext( _rDriver.getContext() ) + ,m_pDriver( &_rDriver ) + ,m_pDriverobject(nullptr) + ,m_pDriverClassLoader() + ,m_Driver_theClass(nullptr) + ,m_aLogger( _rDriver.getLogger() ) + ,m_bIgnoreDriverPrivileges(true) + ,m_bIgnoreCurrency(false) +{ +} + +java_sql_Connection::~java_sql_Connection() +{ + ::rtl::Reference< jvmaccess::VirtualMachine > xTest = java_lang_Object::getVM(); + if ( !xTest.is() ) + return; + + SDBThreadAttach t; + clearObject(*t.pEnv); + + { + if ( m_pDriverobject ) + t.pEnv->DeleteGlobalRef( m_pDriverobject ); + m_pDriverobject = nullptr; + if ( m_Driver_theClass ) + t.pEnv->DeleteGlobalRef( m_Driver_theClass ); + m_Driver_theClass = nullptr; + } + SDBThreadAttach::releaseRef(); +} + +void java_sql_Connection::disposing() +{ + ::osl::MutexGuard aGuard(m_aMutex); + + m_aLogger.log( LogLevel::INFO, STR_LOG_SHUTDOWN_CONNECTION ); + + java_sql_Connection_BASE::disposing(); + + if ( object ) + { + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("close", mID); + } +} + +jclass java_sql_Connection::getMyClass() const +{ + // the class must be fetched only once, therefore static + if( !theClass ) + theClass = findMyClass("java/sql/Connection"); + return theClass; +} + + +OUString SAL_CALL java_sql_Connection::getCatalog( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed); + + static jmethodID mID(nullptr); + return callStringMethod("getCatalog",mID); +} + +Reference< XDatabaseMetaData > SAL_CALL java_sql_Connection::getMetaData( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed); + + + Reference< XDatabaseMetaData > xMetaData = m_xMetaData; + if(!xMetaData.is()) + { + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + static jmethodID mID(nullptr); + jobject out = callObjectMethod(t.pEnv,"getMetaData","()Ljava/sql/DatabaseMetaData;", mID); + if(out) + { + xMetaData = new java_sql_DatabaseMetaData( t.pEnv, out, *this ); + m_xMetaData = xMetaData; + } + } + + return xMetaData; +} + +void SAL_CALL java_sql_Connection::close( ) +{ + dispose(); +} + +void SAL_CALL java_sql_Connection::commit( ) +{ + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("commit", mID); +} + +sal_Bool SAL_CALL java_sql_Connection::isClosed( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + + static jmethodID mID(nullptr); + return callBooleanMethod( "isClosed", mID ) && java_sql_Connection_BASE::rBHelper.bDisposed; +} + +sal_Bool SAL_CALL java_sql_Connection::isReadOnly( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed); + static jmethodID mID(nullptr); + return callBooleanMethod( "isReadOnly", mID ); +} + +void SAL_CALL java_sql_Connection::setCatalog( const OUString& catalog ) +{ + static jmethodID mID(nullptr); + callVoidMethodWithStringArg("setCatalog",mID,catalog); +} + +void SAL_CALL java_sql_Connection::rollback( ) +{ + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("rollback", mID); +} + +sal_Bool SAL_CALL java_sql_Connection::getAutoCommit( ) +{ + static jmethodID mID(nullptr); + return callBooleanMethod( "getAutoCommit", mID ); +} + +void SAL_CALL java_sql_Connection::setReadOnly( sal_Bool readOnly ) +{ + static jmethodID mID(nullptr); + callVoidMethodWithBoolArg_ThrowSQL("setReadOnly", mID, readOnly); +} + +void SAL_CALL java_sql_Connection::setAutoCommit( sal_Bool autoCommit ) +{ + static jmethodID mID(nullptr); + callVoidMethodWithBoolArg_ThrowSQL("setAutoCommit", mID, autoCommit); +} + +Reference< css::container::XNameAccess > SAL_CALL java_sql_Connection::getTypeMap( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed); + + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + static jmethodID mID(nullptr); + callObjectMethod(t.pEnv,"getTypeMap","()Ljava/util/Map;", mID); + // WARNING: the caller becomes the owner of the returned pointer + return nullptr; +} + +void SAL_CALL java_sql_Connection::setTypeMap( const Reference< css::container::XNameAccess >& /*typeMap*/ ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed); + + ::dbtools::throwFeatureNotImplementedSQLException( "XConnection::setTypeMap", *this ); +} + + +sal_Int32 SAL_CALL java_sql_Connection::getTransactionIsolation( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed); + + static jmethodID mID(nullptr); + return callIntMethod_ThrowSQL("getTransactionIsolation", mID); +} + +void SAL_CALL java_sql_Connection::setTransactionIsolation( sal_Int32 level ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed); + + static jmethodID mID(nullptr); + callVoidMethodWithIntArg_ThrowSQL("setTransactionIsolation", mID, level); +} + +Reference< XStatement > SAL_CALL java_sql_Connection::createStatement( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed); + m_aLogger.log( LogLevel::FINE, STR_LOG_CREATE_STATEMENT ); + + SDBThreadAttach t; + java_sql_Statement* pStatement = new java_sql_Statement( t.pEnv, *this ); + Reference< XStatement > xStmt = pStatement; + m_aStatements.push_back( WeakReferenceHelper( xStmt ) ); + + m_aLogger.log( LogLevel::FINE, STR_LOG_CREATED_STATEMENT_ID, pStatement->getStatementObjectID() ); + return xStmt; +} + +Reference< XPreparedStatement > SAL_CALL java_sql_Connection::prepareStatement( const OUString& sql ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed); + m_aLogger.log( LogLevel::FINE, STR_LOG_PREPARE_STATEMENT, sql ); + + SDBThreadAttach t; + + java_sql_PreparedStatement* pStatement = new java_sql_PreparedStatement( t.pEnv, *this, sql ); + Reference< XPreparedStatement > xReturn( pStatement ); + m_aStatements.push_back(WeakReferenceHelper(xReturn)); + + m_aLogger.log( LogLevel::FINE, STR_LOG_PREPARED_STATEMENT_ID, pStatement->getStatementObjectID() ); + return xReturn; +} + +Reference< XPreparedStatement > SAL_CALL java_sql_Connection::prepareCall( const OUString& sql ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed); + m_aLogger.log( LogLevel::FINE, STR_LOG_PREPARE_CALL, sql ); + + SDBThreadAttach t; + + java_sql_CallableStatement* pStatement = new java_sql_CallableStatement( t.pEnv, *this, sql ); + Reference< XPreparedStatement > xStmt( pStatement ); + m_aStatements.push_back(WeakReferenceHelper(xStmt)); + + m_aLogger.log( LogLevel::FINE, STR_LOG_PREPARED_CALL_ID, pStatement->getStatementObjectID() ); + return xStmt; +} + +OUString SAL_CALL java_sql_Connection::nativeSQL( const OUString& sql ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed); + + OUString aStr; + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + { + + // initialize temporary Variable + static const char * const cSignature = "(Ljava/lang/String;)Ljava/lang/String;"; + static const char * const cMethodName = "nativeSQL"; + // Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + // Convert Parameter + jdbc::LocalRef< jstring > str( t.env(),convertwchar_tToJavaString(t.pEnv,sql)); + + jobject out = t.pEnv->CallObjectMethod( object, mID, str.get() ); + aStr = JavaString2String(t.pEnv, static_cast<jstring>(out) ); + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + } //t.pEnv + + m_aLogger.log( LogLevel::FINER, STR_LOG_NATIVE_SQL, sql, aStr ); + + return aStr; +} + +void SAL_CALL java_sql_Connection::clearWarnings( ) +{ + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("clearWarnings", mID); +} + +Any SAL_CALL java_sql_Connection::getWarnings( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Connection_BASE::rBHelper.bDisposed); + + SDBThreadAttach t; + static jmethodID mID(nullptr); + jobject out = callObjectMethod(t.pEnv,"getWarnings","()Ljava/sql/SQLWarning;", mID); + // WARNING: the caller becomes the owner of the returned pointer + if( out ) + { + java_sql_SQLWarning_BASE warn_base(t.pEnv, out); + SQLException aAsException( java_sql_SQLWarning( warn_base, *this ) ); + + // translate to warning + SQLWarning aWarning; + aWarning.Context = aAsException.Context; + aWarning.Message = aAsException.Message; + aWarning.SQLState = aAsException.SQLState; + aWarning.ErrorCode = aAsException.ErrorCode; + aWarning.NextException = aAsException.NextException; + + return makeAny( aWarning ); + } + + return Any(); +} + + +namespace +{ + OUString lcl_getDriverLoadErrorMessage( const ::connectivity::SharedResources& _aResource,const OUString& _rDriverClass, const OUString& _rDriverClassPath ) + { + OUString sError1( _aResource.getResourceStringWithSubstitution( + STR_NO_CLASSNAME, + "$classname$", _rDriverClass + ) ); + if ( !_rDriverClassPath.isEmpty() ) + { + const OUString sError2( _aResource.getResourceStringWithSubstitution( + STR_NO_CLASSNAME_PATH, + "$classpath$", _rDriverClassPath + ) ); + sError1 += sError2; + } // if ( _rDriverClassPath.getLength() ) + return sError1; + } +} + + +namespace +{ + bool lcl_setSystemProperties_nothrow( const java::sql::ConnectionLog& _rLogger, + JNIEnv& _rEnv, const Sequence< NamedValue >& _rSystemProperties ) + { + if ( !_rSystemProperties.hasElements() ) + // nothing to do + return true; + + LocalRef< jclass > systemClass( _rEnv ); + jmethodID nSetPropertyMethodID = nullptr; + // retrieve the java.lang.System class + systemClass.set( _rEnv.FindClass( "java/lang/System" ) ); + if ( systemClass.is() ) + { + nSetPropertyMethodID = _rEnv.GetStaticMethodID( + systemClass.get(), "setProperty", "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/String;" ); + } + + if ( nSetPropertyMethodID == nullptr ) + return false; + + for ( auto const & systemProp : _rSystemProperties ) + { + OUString sValue; + OSL_VERIFY( systemProp.Value >>= sValue ); + + _rLogger.log( LogLevel::FINER, STR_LOG_SETTING_SYSTEM_PROPERTY, systemProp.Name, sValue ); + + LocalRef< jstring > jName( _rEnv, convertwchar_tToJavaString( &_rEnv, systemProp.Name ) ); + LocalRef< jstring > jValue( _rEnv, convertwchar_tToJavaString( &_rEnv, sValue ) ); + + _rEnv.CallStaticObjectMethod( systemClass.get(), nSetPropertyMethodID, jName.get(), jValue.get() ); + LocalRef< jthrowable > throwable( _rEnv, _rEnv.ExceptionOccurred() ); + if ( throwable.is() ) + return false; + } + + return true; + } +} + + +void java_sql_Connection::loadDriverFromProperties( const OUString& _sDriverClass, const OUString& _sDriverClassPath, + const Sequence< NamedValue >& _rSystemProperties ) +{ + // first try if the jdbc driver is already registered at the driver manager + SDBThreadAttach t; + try + { + if ( !object ) + { + if ( !lcl_setSystemProperties_nothrow( getLogger(), *t.pEnv, _rSystemProperties ) ) + ThrowLoggedSQLException( getLogger(), t.pEnv, *this ); + + m_pDriverClassLoader.reset(); + + // here I try to find the class for jdbc driver + java_sql_SQLException_BASE::st_getMyClass(); + java_lang_Throwable::st_getMyClass(); + + if ( _sDriverClass.isEmpty() ) + { + m_aLogger.log( LogLevel::SEVERE, STR_LOG_NO_DRIVER_CLASS ); + ::dbtools::throwGenericSQLException( + lcl_getDriverLoadErrorMessage( getResources(),_sDriverClass, _sDriverClassPath ), + *this + ); + } + else + { + m_aLogger.log( LogLevel::INFO, STR_LOG_LOADING_DRIVER, _sDriverClass ); + // the driver manager holds the class of the driver for later use + std::unique_ptr< java_lang_Class > pDrvClass; + if ( _sDriverClassPath.isEmpty() ) + { + // if forName didn't find the class it will throw an exception + pDrvClass.reset(java_lang_Class::forName(_sDriverClass)); + } + else + { + LocalRef< jclass > driverClass(t.env()); + LocalRef< jobject > driverClassLoader(t.env()); + + loadClass( + m_pDriver->getContext(), + t.env(), _sDriverClassPath, _sDriverClass, &driverClassLoader, &driverClass ); + + m_pDriverClassLoader.set( driverClassLoader ); + pDrvClass.reset( new java_lang_Class( t.pEnv, driverClass.release() ) ); + + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + } + if (pDrvClass) + { + LocalRef< jobject > driverObject( t.env() ); + driverObject.set( pDrvClass->newInstanceObject() ); + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + m_pDriverobject = driverObject.release(); + + if( m_pDriverobject ) + m_pDriverobject = t.pEnv->NewGlobalRef( m_pDriverobject ); + + { + jclass tempClass = t.pEnv->GetObjectClass(m_pDriverobject); + if ( m_pDriverobject ) + { + m_Driver_theClass = static_cast<jclass>(t.pEnv->NewGlobalRef( tempClass )); + t.pEnv->DeleteLocalRef( tempClass ); + } + } + } + m_aLogger.log( LogLevel::INFO, STR_LOG_CONN_SUCCESS ); + } + } + } + catch( const SQLException& ) + { + css::uno::Any anyEx = cppu::getCaughtException(); + throw SQLException( + lcl_getDriverLoadErrorMessage( getResources(),_sDriverClass, _sDriverClassPath ), + *this, + OUString(), + 1000, + anyEx); + } + catch( Exception& ) + { + css::uno::Any anyEx = cppu::getCaughtException(); + ::dbtools::throwGenericSQLException( + lcl_getDriverLoadErrorMessage( getResources(),_sDriverClass, _sDriverClassPath ), + *this, + anyEx + ); + } +} + +OUString java_sql_Connection::impl_getJavaDriverClassPath_nothrow(const OUString& _sDriverClass) +{ + static const char s_sNodeName[] = "org.openoffice.Office.DataAccess/JDBC/DriverClassPaths"; + ::utl::OConfigurationTreeRoot aNamesRoot = ::utl::OConfigurationTreeRoot::createWithComponentContext( + m_pDriver->getContext(), s_sNodeName, -1, ::utl::OConfigurationTreeRoot::CM_READONLY); + OUString sURL; + if ( aNamesRoot.isValid() && aNamesRoot.hasByName( _sDriverClass ) ) + { + ::utl::OConfigurationNode aRegisterObj = aNamesRoot.openNode( _sDriverClass ); + OSL_VERIFY( aRegisterObj.getNodeValue( "Path" ) >>= sURL ); + } + return sURL; +} + +bool java_sql_Connection::construct(const OUString& url, + const Sequence< PropertyValue >& info) +{ + { // initialize the java vm + ::rtl::Reference< jvmaccess::VirtualMachine > xTest = java_lang_Object::getVM(m_xContext); + if ( !xTest.is() ) + throwGenericSQLException(STR_NO_JAVA,*this); + } + SDBThreadAttach t; + SDBThreadAttach::addRef(); // will be released in dtor + if ( !t.pEnv ) + throwGenericSQLException(STR_NO_JAVA,*this); + + OUString sGeneratedValueStatement; // contains the statement which should be used when query for automatically generated values + bool bAutoRetrievingEnabled = false; // set to <TRUE/> when we should allow to query for generated values + OUString sDriverClassPath,sDriverClass; + Sequence< NamedValue > aSystemProperties; + + ::comphelper::NamedValueCollection aSettings( info ); + sDriverClass = aSettings.getOrDefault( "JavaDriverClass", sDriverClass ); + sDriverClassPath = aSettings.getOrDefault( "JavaDriverClassPath", sDriverClassPath); + if ( sDriverClassPath.isEmpty() ) + sDriverClassPath = impl_getJavaDriverClassPath_nothrow(sDriverClass); + bAutoRetrievingEnabled = aSettings.getOrDefault( "IsAutoRetrievingEnabled", bAutoRetrievingEnabled ); + sGeneratedValueStatement = aSettings.getOrDefault( "AutoRetrievingStatement", sGeneratedValueStatement ); + m_bIgnoreDriverPrivileges = aSettings.getOrDefault( "IgnoreDriverPrivileges", m_bIgnoreDriverPrivileges ); + m_bIgnoreCurrency = aSettings.getOrDefault( "IgnoreCurrency", m_bIgnoreCurrency ); + aSystemProperties = aSettings.getOrDefault( "SystemProperties", aSystemProperties ); + m_aCatalogRestriction = aSettings.getOrDefault( "ImplicitCatalogRestriction", Any() ); + m_aSchemaRestriction = aSettings.getOrDefault( "ImplicitSchemaRestriction", Any() ); + + loadDriverFromProperties( sDriverClass, sDriverClassPath, aSystemProperties ); + + enableAutoRetrievingEnabled(bAutoRetrievingEnabled); + setAutoRetrievingStatement(sGeneratedValueStatement); + + if ( t.pEnv && m_Driver_theClass && m_pDriverobject ) + { + // Java-Call + static const char * const cSignature = "(Ljava/lang/String;Ljava/util/Properties;)Ljava/sql/Connection;"; + static const char * const cMethodName = "connect"; + jmethodID mID = t.pEnv->GetMethodID( m_Driver_theClass, cMethodName, cSignature ); + + if ( mID ) + { + jvalue args[2]; + // convert Parameter + args[0].l = convertwchar_tToJavaString(t.pEnv,url); + std::unique_ptr<java_util_Properties> pProps = createStringPropertyArray(info); + args[1].l = pProps->getJavaObject(); + + LocalRef< jobject > ensureDelete( t.env(), args[0].l ); + + jobject out = nullptr; + // In some cases (e.g., + // connectivity/source/drivers/hsqldb/HDriver.cxx:1.24 + // l. 249) the JavaDriverClassPath contains multiple jars, + // as creating the JavaDriverClass instance requires + // (reflective) access to those other jars. Now, if the + // JavaDriverClass is actually loaded by some parent class + // loader (e.g., because its jar is also on the global + // class path), it would still not have access to the + // additional jars on the JavaDriverClassPath. Hence, the + // JavaDriverClassPath class loader is pushed as context + // class loader around the JavaDriverClass instance + // creation: + // #i82222# / 2007-10-15 + { + ContextClassLoaderScope ccl( t.env(), getDriverClassLoader(), getLogger(), *this ); + out = t.pEnv->CallObjectMethod( m_pDriverobject, mID, args[0].l,args[1].l ); + pProps.reset(); + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + } + + if ( !out ) + m_aLogger.log( LogLevel::SEVERE, STR_LOG_NO_SYSTEM_CONNECTION ); + + if ( out ) + object = t.pEnv->NewGlobalRef( out ); + + if ( object ) + m_aLogger.log( LogLevel::INFO, STR_LOG_GOT_JDBC_CONNECTION, url ); + + m_aConnectionInfo = info; + } //mID + } //t.pEnv + return object != nullptr; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/JDriver.cxx b/connectivity/source/drivers/jdbc/JDriver.cxx new file mode 100644 index 000000000..3ec181bb3 --- /dev/null +++ b/connectivity/source/drivers/jdbc/JDriver.cxx @@ -0,0 +1,246 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <java/sql/Driver.hxx> +#include <java/sql/Connection.hxx> +#include <sal/log.hxx> +#include <connectivity/dbexception.hxx> +#include <jvmfwk/framework.hxx> +#include <strings.hrc> +#include <resource/sharedresources.hxx> +#include <comphelper/processfactory.hxx> +#include <cppuhelper/supportsservice.hxx> +#include <strings.hxx> + +using namespace connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; + + +java_sql_Driver::java_sql_Driver(const Reference< css::uno::XComponentContext >& _rxContext) + :m_aContext( _rxContext ) + ,m_aLogger( _rxContext, "org.openoffice.sdbc.jdbcBridge" ) +{ +} + +java_sql_Driver::~java_sql_Driver() +{ +} + +// static ServiceInfo + +OUString java_sql_Driver::getImplementationName_Static( ) +{ + return "com.sun.star.comp.sdbc.JDBCDriver"; + // this name is referenced in the configuration and in the jdbc.xml + // Please take care when changing it. +} + +Sequence< OUString > java_sql_Driver::getSupportedServiceNames_Static( ) +{ + Sequence<OUString> aSNS { "com.sun.star.sdbc.Driver" }; + return aSNS; +} + +css::uno::Reference< css::uno::XInterface > connectivity::java_sql_Driver_CreateInstance(const css::uno::Reference< css::lang::XMultiServiceFactory >& _rxFactory) +{ + return *(new java_sql_Driver( comphelper::getComponentContext(_rxFactory))); +} + +OUString SAL_CALL java_sql_Driver::getImplementationName( ) +{ + return getImplementationName_Static(); +} + +sal_Bool SAL_CALL java_sql_Driver::supportsService( const OUString& _rServiceName ) +{ + return cppu::supportsService(this, _rServiceName); +} + + +Sequence< OUString > SAL_CALL java_sql_Driver::getSupportedServiceNames( ) +{ + return getSupportedServiceNames_Static(); +} + +Reference< XConnection > SAL_CALL java_sql_Driver::connect( const OUString& url, const + Sequence< PropertyValue >& info ) +{ + m_aLogger.log( LogLevel::INFO, STR_LOG_DRIVER_CONNECTING_URL, url ); + + Reference< XConnection > xOut; + if ( acceptsURL(url ) ) + { + java_sql_Connection* pConnection = new java_sql_Connection( *this ); + xOut = pConnection; + if ( !pConnection->construct(url,info) ) + xOut.clear(); // an error occurred and the java driver didn't throw an exception + else + m_aLogger.log( LogLevel::INFO, STR_LOG_DRIVER_SUCCESS ); + } + return xOut; +} + +sal_Bool SAL_CALL java_sql_Driver::acceptsURL( const OUString& url ) +{ + // don't ask the real driver for the url + // I feel responsible for all jdbc url's + bool bEnabled = false; + javaFrameworkError e = jfw_getEnabled(&bEnabled); + switch (e) { + case JFW_E_NONE: + break; + case JFW_E_DIRECT_MODE: + SAL_INFO( + "connectivity.jdbc", + "jfw_getEnabled: JFW_E_DIRECT_MODE, assuming true"); + bEnabled = true; + break; + default: + SAL_WARN("connectivity.jdbc", "jfw_getEnabled: error code " << +e); + break; + } + return bEnabled && url.startsWith("jdbc:"); +} + +Sequence< DriverPropertyInfo > SAL_CALL java_sql_Driver::getPropertyInfo( const OUString& url, + const Sequence< PropertyValue >& /*info*/ ) +{ + if ( acceptsURL(url) ) + { + std::vector< DriverPropertyInfo > aDriverInfo; + + Sequence< OUString > aBooleanValues(2); + aBooleanValues[0] = "false"; + aBooleanValues[1] = "true"; + + aDriverInfo.push_back(DriverPropertyInfo( + "JavaDriverClass" + ,"The JDBC driver class name." + ,true + ,OUString() + ,Sequence< OUString >()) + ); + aDriverInfo.push_back(DriverPropertyInfo( + "JavaDriverClassPath" + ,"The class path where to look for the JDBC driver." + ,true + , "" + ,Sequence< OUString >()) + ); + aDriverInfo.push_back(DriverPropertyInfo( + "SystemProperties" + ,"Additional properties to set at java.lang.System before loading the driver." + ,true + , "" + ,Sequence< OUString >()) + ); + aDriverInfo.push_back(DriverPropertyInfo( + "ParameterNameSubstitution" + ,"Change named parameters with '?'." + ,false + ,"false" + ,aBooleanValues) + ); + aDriverInfo.push_back(DriverPropertyInfo( + "IgnoreDriverPrivileges" + ,"Ignore the privileges from the database driver." + ,false + , "false" + ,aBooleanValues) + ); + aDriverInfo.push_back(DriverPropertyInfo( + "IsAutoRetrievingEnabled" + ,"Retrieve generated values." + ,false + ,"false" + ,aBooleanValues) + ); + aDriverInfo.push_back(DriverPropertyInfo( + "AutoRetrievingStatement" + ,"Auto-increment statement." + ,false + ,OUString() + ,Sequence< OUString >()) + ); + aDriverInfo.push_back(DriverPropertyInfo( + "GenerateASBeforeCorrelationName" + ,"Generate AS before table correlation names." + ,false + ,"false" + ,aBooleanValues) + ); + aDriverInfo.push_back(DriverPropertyInfo( + "IgnoreCurrency" + ,"Ignore the currency field from the ResultsetMetaData." + ,false + ,"false" + ,aBooleanValues) + ); + aDriverInfo.push_back(DriverPropertyInfo( + "EscapeDateTime" + ,"Escape date time format." + ,false + ,"true" + ,aBooleanValues) + ); + aDriverInfo.push_back(DriverPropertyInfo( + "TypeInfoSettings" + ,"Defines how the type info of the database metadata should be manipulated." + ,false + ,OUString( ) + ,Sequence< OUString > ()) + ); + aDriverInfo.push_back(DriverPropertyInfo( + "ImplicitCatalogRestriction" + ,"The catalog which should be used in getTables calls, when the caller passed NULL." + ,false + ,OUString( ) + ,Sequence< OUString > ()) + ); + aDriverInfo.push_back(DriverPropertyInfo( + "ImplicitSchemaRestriction" + ,"The schema which should be used in getTables calls, when the caller passed NULL." + ,false + ,OUString( ) + ,Sequence< OUString > ()) + ); + return Sequence< DriverPropertyInfo >(aDriverInfo.data(),aDriverInfo.size()); + } + ::connectivity::SharedResources aResources; + const OUString sMessage = aResources.getResourceString(STR_URI_SYNTAX_ERROR); + ::dbtools::throwGenericSQLException(sMessage ,*this); + return Sequence< DriverPropertyInfo >(); +} + +sal_Int32 SAL_CALL java_sql_Driver::getMajorVersion( ) +{ + return 1; +} + +sal_Int32 SAL_CALL java_sql_Driver::getMinorVersion( ) +{ + return 0; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/JStatement.cxx b/connectivity/source/drivers/jdbc/JStatement.cxx new file mode 100644 index 000000000..9bfe11838 --- /dev/null +++ b/connectivity/source/drivers/jdbc/JStatement.cxx @@ -0,0 +1,823 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <java/sql/JStatement.hxx> +#include <java/sql/ResultSet.hxx> +#include <java/sql/Connection.hxx> +#include <java/sql/SQLWarning.hxx> +#include <java/tools.hxx> +#include <java/ContextClassLoader.hxx> +#include <comphelper/property.hxx> +#include <com/sun/star/lang/DisposedException.hpp> +#include <cppuhelper/typeprovider.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <comphelper/sequence.hxx> +#include <TConnection.hxx> +#include <comphelper/types.hxx> +#include <tools/diagnose_ex.h> +#include <com/sun/star/sdbc/ResultSetConcurrency.hpp> +#include <com/sun/star/sdbc/ResultSetType.hpp> + +#include <strings.hxx> + +#include <algorithm> +#include <string.h> + +using namespace ::comphelper; +using namespace connectivity; +using namespace ::cppu; + +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; + + +//************ Class: java.sql.Statement + + +jclass java_sql_Statement_Base::theClass = nullptr; + + +java_sql_Statement_Base::java_sql_Statement_Base( JNIEnv * pEnv, java_sql_Connection& _rCon ) + :java_sql_Statement_BASE(m_aMutex) + ,java_lang_Object( pEnv, nullptr ) + ,OPropertySetHelper(java_sql_Statement_BASE::rBHelper) + ,m_pConnection( &_rCon ) + ,m_aLogger( _rCon.getLogger(), java::sql::ConnectionLog::STATEMENT ) + ,m_nResultSetConcurrency(ResultSetConcurrency::READ_ONLY) + ,m_nResultSetType(ResultSetType::FORWARD_ONLY) + ,m_bEscapeProcessing(true) +{ +} + + +java_sql_Statement_Base::~java_sql_Statement_Base() +{ +} + + +void SAL_CALL OStatement_BASE2::disposing() +{ + ::osl::MutexGuard aGuard(m_aMutex); + + if ( object ) + { + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("close", mID); + } + + ::comphelper::disposeComponent(m_xGeneratedStatement); + m_pConnection.clear(); + + java_sql_Statement_Base::disposing(); +} + +jclass java_sql_Statement_Base::getMyClass() const +{ + // the class must be fetched only once, therefore static + if( !theClass ) + theClass = findMyClass("java/sql/Statement"); + return theClass; +} + +void SAL_CALL java_sql_Statement_Base::disposing() +{ + m_aLogger.log( LogLevel::FINE, STR_LOG_CLOSING_STATEMENT ); + java_sql_Statement_BASE::disposing(); + clearObject(); +} + + +Any SAL_CALL java_sql_Statement_Base::queryInterface( const Type & rType ) +{ + if ( m_pConnection.is() && !m_pConnection->isAutoRetrievingEnabled() && rType == cppu::UnoType<XGeneratedResultSet>::get()) + return Any(); + Any aRet( java_sql_Statement_BASE::queryInterface(rType) ); + return aRet.hasValue() ? aRet : OPropertySetHelper::queryInterface(rType); +} + +Sequence< Type > SAL_CALL java_sql_Statement_Base::getTypes( ) +{ + ::cppu::OTypeCollection aTypes( cppu::UnoType<css::beans::XMultiPropertySet>::get(), + cppu::UnoType<css::beans::XFastPropertySet>::get(), + cppu::UnoType<css::beans::XPropertySet>::get()); + + Sequence< Type > aOldTypes = java_sql_Statement_BASE::getTypes(); + if ( m_pConnection.is() && !m_pConnection->isAutoRetrievingEnabled() ) + { + auto newEnd = std::remove(aOldTypes.begin(), aOldTypes.end(), + cppu::UnoType<XGeneratedResultSet>::get()); + aOldTypes.realloc(std::distance(aOldTypes.begin(), newEnd)); + } + + return ::comphelper::concatSequences(aTypes.getTypes(),aOldTypes); +} + +Reference< XResultSet > SAL_CALL java_sql_Statement_Base::getGeneratedValues( ) +{ + m_aLogger.log( LogLevel::FINE, STR_LOG_GENERATED_VALUES ); + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + + jobject out(nullptr); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + // initialize temporary Variable + try + { + static jmethodID mID(nullptr); + out = callResultSetMethod(t.env(),"getGeneratedKeys",mID); + } + catch(const SQLException&) + { + // ignore + } + + Reference< XResultSet > xRes; + if ( !out ) + { + OSL_ENSURE( m_pConnection.is() && m_pConnection->isAutoRetrievingEnabled(),"Illegal call here. isAutoRetrievingEnabled is false!"); + if ( m_pConnection.is() ) + { + OUString sStmt = m_pConnection->getTransformedGeneratedStatement(m_sSqlStatement); + if ( !sStmt.isEmpty() ) + { + m_aLogger.log( LogLevel::FINER, STR_LOG_GENERATED_VALUES_FALLBACK, sStmt ); + ::comphelper::disposeComponent(m_xGeneratedStatement); + m_xGeneratedStatement = m_pConnection->createStatement(); + xRes = m_xGeneratedStatement->executeQuery(sStmt); + } + } + } + else + xRes = new java_sql_ResultSet( t.pEnv, out, m_aLogger,*m_pConnection, this ); + return xRes; +} + + +void SAL_CALL java_sql_Statement_Base::cancel( ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + callVoidMethod_ThrowRuntime("cancel",mID); +} + + +void SAL_CALL java_sql_Statement_Base::close( ) +{ + { + ::osl::MutexGuard aGuard( m_aMutex ); + if (java_sql_Statement_BASE::rBHelper.bDisposed) + throw DisposedException(); + } + dispose(); +} + + +void SAL_CALL java_sql_Statement::clearBatch( ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + { + + createStatement(t.pEnv); + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("clearBatch", mID); + } //t.pEnv +} + + +sal_Bool SAL_CALL java_sql_Statement_Base::execute( const OUString& sql ) +{ + m_aLogger.log( LogLevel::FINE, STR_LOG_EXECUTE_STATEMENT, sql ); + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + + bool out(false); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + { + createStatement(t.pEnv); + m_sSqlStatement = sql; + // initialize temporary Variable + static const char * const cSignature = "(Ljava/lang/String;)Z"; + static const char * const cMethodName = "execute"; + // Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + // convert Parameter + jdbc::LocalRef< jstring > str( t.env(), convertwchar_tToJavaString( t.pEnv, sql ) ); + { + jdbc::ContextClassLoaderScope ccl( t.env(), + m_pConnection.is() ? m_pConnection->getDriverClassLoader() : jdbc::GlobalRef< jobject >(), + m_aLogger, + *this + ); + + out = t.pEnv->CallBooleanMethod( object, mID, str.get() ); + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + } + } //t.pEnv + return out; +} + + +Reference< XResultSet > SAL_CALL java_sql_Statement_Base::executeQuery( const OUString& sql ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + m_aLogger.log( LogLevel::FINE, STR_LOG_EXECUTE_QUERY, sql ); + + jobject out(nullptr); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + + { + createStatement(t.pEnv); + m_sSqlStatement = sql; + // initialize temporary variable + static const char * const cSignature = "(Ljava/lang/String;)Ljava/sql/ResultSet;"; + static const char * const cMethodName = "executeQuery"; + // Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + // convert Parameter + jdbc::LocalRef< jstring > str( t.env(), convertwchar_tToJavaString( t.pEnv, sql ) ); + { + jdbc::ContextClassLoaderScope ccl( t.env(), + m_pConnection.is() ? m_pConnection->getDriverClassLoader() : jdbc::GlobalRef< jobject >(), + m_aLogger, + *this + ); + + out = t.pEnv->CallObjectMethod( object, mID, str.get() ); + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + } + } //t.pEnv + // WARNING: the caller becomes the owner of the returned pointer + return out==nullptr ? nullptr : new java_sql_ResultSet( t.pEnv, out, m_aLogger, *m_pConnection,this ); +} + +Reference< XConnection > SAL_CALL java_sql_Statement_Base::getConnection( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + return Reference< XConnection >(m_pConnection.get()); +} + + +Any SAL_CALL java_sql_Statement::queryInterface( const Type & rType ) +{ + Any aRet = ::cppu::queryInterface(rType,static_cast< XBatchExecution*> (this)); + return aRet.hasValue() ? aRet : java_sql_Statement_Base::queryInterface(rType); +} + + +void SAL_CALL java_sql_Statement::addBatch( const OUString& sql ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + { + createStatement(t.pEnv); + static jmethodID mID(nullptr); + callVoidMethodWithStringArg("addBatch",mID,sql); + } //t.pEnv +} + + +Sequence< sal_Int32 > SAL_CALL java_sql_Statement::executeBatch( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + Sequence< sal_Int32 > aSeq; + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + jintArray out = static_cast<jintArray>(callObjectMethod(t.pEnv,"executeBatch","()[I", mID)); + if (out) + { + jboolean p = false; + aSeq.realloc(t.pEnv->GetArrayLength(out)); + memcpy(aSeq.getArray(),t.pEnv->GetIntArrayElements(out,&p),aSeq.getLength()); + t.pEnv->DeleteLocalRef(out); + } + return aSeq; +} + + +sal_Int32 SAL_CALL java_sql_Statement_Base::executeUpdate( const OUString& sql ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + m_aLogger.log( LogLevel::FINE, STR_LOG_EXECUTE_UPDATE, sql ); + + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + m_sSqlStatement = sql; + static jmethodID mID(nullptr); + return callIntMethodWithStringArg("executeUpdate",mID,sql); +} + + +Reference< css::sdbc::XResultSet > SAL_CALL java_sql_Statement_Base::getResultSet( ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + jobject out = callResultSetMethod(t.env(),"getResultSet",mID); + + // WARNING: the caller becomes the owner of the returned pointer + return out==nullptr ? nullptr : new java_sql_ResultSet( t.pEnv, out, m_aLogger, *m_pConnection,this ); +} + + +sal_Int32 SAL_CALL java_sql_Statement_Base::getUpdateCount( ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + sal_Int32 out = callIntMethod_ThrowSQL("getUpdateCount", mID); + m_aLogger.log( LogLevel::FINER, STR_LOG_UPDATE_COUNT, out ); + return out; +} + + +sal_Bool SAL_CALL java_sql_Statement_Base::getMoreResults( ) +{ + static jmethodID mID(nullptr); + return callBooleanMethod( "getMoreResults", mID ); +} + + +Any SAL_CALL java_sql_Statement_Base::getWarnings( ) +{ + SDBThreadAttach t; + createStatement(t.pEnv); + static jmethodID mID(nullptr); + jobject out = callObjectMethod(t.pEnv,"getWarnings","()Ljava/sql/SQLWarning;", mID); + // WARNING: the caller becomes the owner of the returned pointer + if( out ) + { + java_sql_SQLWarning_BASE warn_base( t.pEnv, out ); + return makeAny( + static_cast< css::sdbc::SQLException >( + java_sql_SQLWarning(warn_base,*static_cast<cppu::OWeakObject*>(this)))); + } + + return Any(); +} + +void SAL_CALL java_sql_Statement_Base::clearWarnings( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + SDBThreadAttach t; + + { + createStatement(t.pEnv); + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("clearWarnings", mID); + } +} + +sal_Int32 java_sql_Statement_Base::getQueryTimeOut() +{ + static jmethodID mID(nullptr); + return impl_getProperty("getQueryTimeOut",mID); +} + +sal_Int32 java_sql_Statement_Base::getMaxRows() +{ + static jmethodID mID(nullptr); + return impl_getProperty("getMaxRows",mID); +} + +sal_Int32 java_sql_Statement_Base::getResultSetConcurrency() +{ + static jmethodID mID(nullptr); + return impl_getProperty("getResultSetConcurrency",mID,m_nResultSetConcurrency); +} + + +sal_Int32 java_sql_Statement_Base::getResultSetType() +{ + static jmethodID mID(nullptr); + return impl_getProperty("getResultSetType",mID,m_nResultSetType); +} + +sal_Int32 java_sql_Statement_Base::impl_getProperty(const char* _pMethodName, jmethodID& _inout_MethodID,sal_Int32 _nDefault) +{ + sal_Int32 out = _nDefault; + if ( object ) + out = callIntMethod_ThrowRuntime(_pMethodName, _inout_MethodID); + return out; +} + +sal_Int32 java_sql_Statement_Base::impl_getProperty(const char* _pMethodName, jmethodID& _inout_MethodID) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + return callIntMethod_ThrowRuntime(_pMethodName, _inout_MethodID); +} + +sal_Int32 java_sql_Statement_Base::getFetchDirection() +{ + static jmethodID mID(nullptr); + return impl_getProperty("getFetchDirection",mID); +} + +sal_Int32 java_sql_Statement_Base::getFetchSize() +{ + static jmethodID mID(nullptr); + return impl_getProperty("getFetchSize",mID); +} + +sal_Int32 java_sql_Statement_Base::getMaxFieldSize() +{ + static jmethodID mID(nullptr); + return impl_getProperty("getMaxFieldSize",mID); +} + +OUString java_sql_Statement_Base::getCursorName() +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + try + { + return callStringMethod("getCursorName",mID); + } + catch(const SQLException&) + { + } + return OUString(); +} + +void java_sql_Statement_Base::setQueryTimeOut(sal_Int32 _par0) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + callVoidMethodWithIntArg_ThrowRuntime("setQueryTimeOut", mID, _par0); +} + + +void java_sql_Statement_Base::setEscapeProcessing(bool _par0) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + m_aLogger.log( LogLevel::FINE, STR_LOG_SET_ESCAPE_PROCESSING, _par0 ); + + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + m_bEscapeProcessing = _par0; + createStatement( t.pEnv ); + static jmethodID mID(nullptr); + callVoidMethodWithBoolArg_ThrowRuntime("setEscapeProcessing", mID, _par0); +} + +void java_sql_Statement_Base::setMaxRows(sal_Int32 _par0) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + callVoidMethodWithIntArg_ThrowRuntime("setMaxRows", mID, _par0); +} + +void java_sql_Statement_Base::setResultSetConcurrency(sal_Int32 _par0) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + m_aLogger.log( LogLevel::FINE, STR_LOG_RESULT_SET_CONCURRENCY, _par0 ); + m_nResultSetConcurrency = _par0; + + clearObject(); +} + +void java_sql_Statement_Base::setResultSetType(sal_Int32 _par0) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + m_aLogger.log( LogLevel::FINE, STR_LOG_RESULT_SET_TYPE, _par0 ); + m_nResultSetType = _par0; + + clearObject(); +} + +void java_sql_Statement_Base::setFetchDirection(sal_Int32 _par0) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + m_aLogger.log( LogLevel::FINER, STR_LOG_FETCH_DIRECTION, _par0 ); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + callVoidMethodWithIntArg_ThrowRuntime("setFetchDirection", mID, _par0); +} + +void java_sql_Statement_Base::setFetchSize(sal_Int32 _par0) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + m_aLogger.log( LogLevel::FINER, STR_LOG_FETCH_SIZE, _par0 ); + + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + callVoidMethodWithIntArg_ThrowRuntime("setFetchSize", mID, _par0); +} + +void java_sql_Statement_Base::setMaxFieldSize(sal_Int32 _par0) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + callVoidMethodWithIntArg_ThrowRuntime("setMaxFieldSize", mID, _par0); +} + +void java_sql_Statement_Base::setCursorName(const OUString &_par0) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + { + createStatement(t.pEnv); + static jmethodID mID(nullptr); + callVoidMethodWithStringArg("setCursorName",mID,_par0); + } //t.pEnv +} + + +::cppu::IPropertyArrayHelper* java_sql_Statement_Base::createArrayHelper( ) const +{ + Sequence< Property > aProps(10); + Property* pProperties = aProps.getArray(); + sal_Int32 nPos = 0; + pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_CURSORNAME), + PROPERTY_ID_CURSORNAME, cppu::UnoType<OUString>::get(), 0); + pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_ESCAPEPROCESSING), + PROPERTY_ID_ESCAPEPROCESSING, cppu::UnoType<bool>::get(), 0); + pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHDIRECTION), + PROPERTY_ID_FETCHDIRECTION, cppu::UnoType<sal_Int32>::get(), 0); + pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHSIZE), + PROPERTY_ID_FETCHSIZE, cppu::UnoType<sal_Int32>::get(), 0); + pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MAXFIELDSIZE), + PROPERTY_ID_MAXFIELDSIZE, cppu::UnoType<sal_Int32>::get(), 0); + pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_MAXROWS), + PROPERTY_ID_MAXROWS, cppu::UnoType<sal_Int32>::get(), 0); + pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_QUERYTIMEOUT), + PROPERTY_ID_QUERYTIMEOUT, cppu::UnoType<sal_Int32>::get(), 0); + pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETCONCURRENCY), + PROPERTY_ID_RESULTSETCONCURRENCY, cppu::UnoType<sal_Int32>::get(), 0); + pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETTYPE), + PROPERTY_ID_RESULTSETTYPE, cppu::UnoType<sal_Int32>::get(), 0); + pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_USEBOOKMARKS), + PROPERTY_ID_USEBOOKMARKS, cppu::UnoType<bool>::get(), 0); + + return new ::cppu::OPropertyArrayHelper(aProps); +} + + +::cppu::IPropertyArrayHelper & java_sql_Statement_Base::getInfoHelper() + +{ + return *getArrayHelper(); +} + +sal_Bool java_sql_Statement_Base::convertFastPropertyValue( + Any & rConvertedValue, + Any & rOldValue, + sal_Int32 nHandle, + const Any& rValue ) +{ + try + { + switch(nHandle) + { + case PROPERTY_ID_QUERYTIMEOUT: + return ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getQueryTimeOut()); + case PROPERTY_ID_MAXFIELDSIZE: + return ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getMaxFieldSize()); + case PROPERTY_ID_MAXROWS: + return ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getMaxRows()); + case PROPERTY_ID_CURSORNAME: + return ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getCursorName()); + case PROPERTY_ID_RESULTSETCONCURRENCY: + return ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getResultSetConcurrency()); + case PROPERTY_ID_RESULTSETTYPE: + return ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getResultSetType()); + case PROPERTY_ID_FETCHDIRECTION: + return ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getFetchDirection()); + case PROPERTY_ID_FETCHSIZE: + return ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getFetchSize()); + case PROPERTY_ID_ESCAPEPROCESSING: + return ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bEscapeProcessing ); + case PROPERTY_ID_USEBOOKMARKS: + // return ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bAsLink); + default: + ; + } + } + catch(const css::lang::IllegalArgumentException&) + { + throw; + } + catch(const css::uno::Exception&) + { + DBG_UNHANDLED_EXCEPTION("connectivity.jdbc"); + } + return false; +} + +void java_sql_Statement_Base::setFastPropertyValue_NoBroadcast( + sal_Int32 nHandle, + const Any& rValue + ) +{ + switch(nHandle) + { + case PROPERTY_ID_QUERYTIMEOUT: + setQueryTimeOut(comphelper::getINT32(rValue)); + break; + case PROPERTY_ID_MAXFIELDSIZE: + setMaxFieldSize(comphelper::getINT32(rValue)); + break; + case PROPERTY_ID_MAXROWS: + setMaxRows(comphelper::getINT32(rValue)); + break; + case PROPERTY_ID_CURSORNAME: + setCursorName(comphelper::getString(rValue)); + break; + case PROPERTY_ID_RESULTSETCONCURRENCY: + setResultSetConcurrency(comphelper::getINT32(rValue)); + break; + case PROPERTY_ID_RESULTSETTYPE: + setResultSetType(comphelper::getINT32(rValue)); + break; + case PROPERTY_ID_FETCHDIRECTION: + setFetchDirection(comphelper::getINT32(rValue)); + break; + case PROPERTY_ID_FETCHSIZE: + setFetchSize(comphelper::getINT32(rValue)); + break; + case PROPERTY_ID_ESCAPEPROCESSING: + setEscapeProcessing( ::comphelper::getBOOL( rValue ) ); + break; + case PROPERTY_ID_USEBOOKMARKS: + // return ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, m_bAsLink); + default: + ; + } +} + +void java_sql_Statement_Base::getFastPropertyValue( + Any& rValue, + sal_Int32 nHandle + ) const +{ + java_sql_Statement_Base* THIS = const_cast<java_sql_Statement_Base*>(this); + try + { + switch(nHandle) + { + case PROPERTY_ID_QUERYTIMEOUT: + rValue <<= THIS->getQueryTimeOut(); + break; + case PROPERTY_ID_MAXFIELDSIZE: + rValue <<= THIS->getMaxFieldSize(); + break; + case PROPERTY_ID_MAXROWS: + rValue <<= THIS->getMaxRows(); + break; + case PROPERTY_ID_CURSORNAME: + rValue <<= THIS->getCursorName(); + break; + case PROPERTY_ID_RESULTSETCONCURRENCY: + rValue <<= THIS->getResultSetConcurrency(); + break; + case PROPERTY_ID_RESULTSETTYPE: + rValue <<= THIS->getResultSetType(); + break; + case PROPERTY_ID_FETCHDIRECTION: + rValue <<= THIS->getFetchDirection(); + break; + case PROPERTY_ID_FETCHSIZE: + rValue <<= THIS->getFetchSize(); + break; + case PROPERTY_ID_ESCAPEPROCESSING: + rValue <<= m_bEscapeProcessing; + break; + case PROPERTY_ID_USEBOOKMARKS: + default: + ; + } + } + catch(const Exception&) + { + } +} + +jclass java_sql_Statement::theClass = nullptr; + +java_sql_Statement::~java_sql_Statement() +{} + +jclass java_sql_Statement::getMyClass() const +{ + // the class must be fetched only once, therefore static + if( !theClass ) + theClass = findMyClass("java/sql/Statement"); + return theClass; +} + + +void java_sql_Statement::createStatement(JNIEnv* _pEnv) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + + if( !(_pEnv && !object) ) + return; + + // initialize temporary variable + static const char * const cMethodName = "createStatement"; + // Java-Call + jobject out = nullptr; + static jmethodID mID(nullptr); + if ( !mID ) + { + static const char * const cSignature = "(II)Ljava/sql/Statement;"; + mID = _pEnv->GetMethodID( m_pConnection->getMyClass(), cMethodName, cSignature ); + } + if( mID ){ + out = _pEnv->CallObjectMethod( m_pConnection->getJavaObject(), mID,m_nResultSetType,m_nResultSetConcurrency ); + } //mID + else + { + static const char * const cSignature2 = "()Ljava/sql/Statement;"; + static jmethodID mID2 = _pEnv->GetMethodID( m_pConnection->getMyClass(), cMethodName, cSignature2 );OSL_ENSURE(mID2,"Unknown method id!"); + if( mID2 ){ + out = _pEnv->CallObjectMethod( m_pConnection->getJavaObject(), mID2); + } //mID + } + ThrowLoggedSQLException( m_aLogger, _pEnv, *this ); + + if ( out ) + object = _pEnv->NewGlobalRef( out ); +} + + +IMPLEMENT_SERVICE_INFO(java_sql_Statement,"com.sun.star.sdbcx.JStatement","com.sun.star.sdbc.Statement"); + +void SAL_CALL java_sql_Statement_Base::acquire() throw() +{ + java_sql_Statement_BASE::acquire(); +} + +void SAL_CALL java_sql_Statement_Base::release() throw() +{ + java_sql_Statement_BASE::release(); +} + +void SAL_CALL java_sql_Statement::acquire() throw() +{ + OStatement_BASE2::acquire(); +} + +void SAL_CALL java_sql_Statement::release() throw() +{ + OStatement_BASE2::release(); +} + +css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL java_sql_Statement_Base::getPropertySetInfo( ) +{ + return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper()); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/Object.cxx b/connectivity/source/drivers/jdbc/Object.cxx new file mode 100644 index 000000000..479699750 --- /dev/null +++ b/connectivity/source/drivers/jdbc/Object.cxx @@ -0,0 +1,483 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <connectivity/CommonTools.hxx> +#include <com/sun/star/lang/WrappedTargetRuntimeException.hpp> +#include <com/sun/star/logging/LogLevel.hpp> +#include <java/tools.hxx> +#include <java/sql/SQLException.hxx> +#include <osl/diagnose.h> +#include <java/LocalRef.hxx> +#include <strings.hxx> + +#include <comphelper/logging.hxx> +#include <cppuhelper/exc_hlp.hxx> + +#include <memory> + +using namespace connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; + + +static ::rtl::Reference< jvmaccess::VirtualMachine > const & getJavaVM2(const ::rtl::Reference< jvmaccess::VirtualMachine >& _rVM = ::rtl::Reference< jvmaccess::VirtualMachine >(), + bool _bSet = false) +{ + static ::rtl::Reference< jvmaccess::VirtualMachine > s_VM; + if ( _rVM.is() || _bSet ) + s_VM = _rVM; + return s_VM; +} + +::rtl::Reference< jvmaccess::VirtualMachine > java_lang_Object::getVM(const Reference<XComponentContext >& _rxContext) +{ + ::rtl::Reference< jvmaccess::VirtualMachine > xVM = getJavaVM2(); + if ( !xVM.is() && _rxContext.is() ) + xVM = getJavaVM2(::connectivity::getJavaVM(_rxContext)); + + return xVM; +} + +SDBThreadAttach::SDBThreadAttach() + : m_aGuard(java_lang_Object::getVM()) + , pEnv(nullptr) +{ + pEnv = m_aGuard.getEnvironment(); + OSL_ENSURE(pEnv,"Environment is nULL!"); +} + +SDBThreadAttach::~SDBThreadAttach() +{ +} + +static oslInterlockedCount& getJavaVMRefCount() +{ + static oslInterlockedCount s_nRefCount = 0; + return s_nRefCount; +} + +void SDBThreadAttach::addRef() +{ + osl_atomic_increment(&getJavaVMRefCount()); +} + +void SDBThreadAttach::releaseRef() +{ + osl_atomic_decrement(&getJavaVMRefCount()); + if ( getJavaVMRefCount() == 0 ) + { + getJavaVM2(::rtl::Reference< jvmaccess::VirtualMachine >(),true); + } +} + +// static variables of the class +jclass java_lang_Object::theClass = nullptr; + +jclass java_lang_Object::getMyClass() const +{ + if( !theClass ) + theClass = findMyClass("java/lang/Object"); + return theClass; +} +// the actual constructor +java_lang_Object::java_lang_Object() + : object( nullptr ) +{ + SDBThreadAttach::addRef(); +} + +// the protected-constructor for the derived classes +java_lang_Object::java_lang_Object( JNIEnv * pXEnv, jobject myObj ) + : object( nullptr ) +{ + SDBThreadAttach::addRef(); + if( pXEnv && myObj ) + object = pXEnv->NewGlobalRef( myObj ); +} + +java_lang_Object::~java_lang_Object() COVERITY_NOEXCEPT_FALSE +{ + if( object ) + { + SDBThreadAttach t; + clearObject(*t.pEnv); + } + SDBThreadAttach::releaseRef(); +} +void java_lang_Object::clearObject(JNIEnv& rEnv) +{ + if( object ) + { + rEnv.DeleteGlobalRef( object ); + object = nullptr; + } +} + +void java_lang_Object::clearObject() +{ + if( object ) + { + SDBThreadAttach t; + clearObject(*t.pEnv); + } +} +// the protected-constructor for the derived classes +void java_lang_Object::saveRef( JNIEnv * pXEnv, jobject myObj ) +{ + OSL_ENSURE( myObj, "object in c++ -> Java Wrapper" ); + if( myObj ) + object = pXEnv->NewGlobalRef( myObj ); +} + + +OUString java_lang_Object::toString() const +{ + static jmethodID mID(nullptr); + return callStringMethod("toString",mID); +} + + +namespace +{ + bool lcl_translateJNIExceptionToUNOException( + JNIEnv* _pEnvironment, const Reference< XInterface >& _rxContext, SQLException& _out_rException ) + { + jthrowable jThrow = _pEnvironment ? _pEnvironment->ExceptionOccurred() : nullptr; + if ( !jThrow ) + return false; + + _pEnvironment->ExceptionClear(); + // we have to clear the exception here because we want to handle it itself + + if ( _pEnvironment->IsInstanceOf( jThrow, java_sql_SQLException_BASE::st_getMyClass() ) ) + { + std::unique_ptr< java_sql_SQLException_BASE > pException( new java_sql_SQLException_BASE( _pEnvironment, jThrow ) ); + _out_rException = SQLException( pException->getMessage(), _rxContext, + pException->getSQLState(), pException->getErrorCode(), Any() ); + return true; + } + else if ( _pEnvironment->IsInstanceOf( jThrow, java_lang_Throwable::st_getMyClass() ) ) + { + std::unique_ptr< java_lang_Throwable > pThrow( new java_lang_Throwable( _pEnvironment, jThrow ) ); +#if OSL_DEBUG_LEVEL > 0 + pThrow->printStackTrace(); +#endif + OUString sMessage = pThrow->getMessage(); + if ( sMessage.isEmpty() ) + sMessage = pThrow->getLocalizedMessage(); + if( sMessage.isEmpty() ) + sMessage = pThrow->toString(); + _out_rException = SQLException( sMessage, _rxContext, OUString(), -1, Any() ); + return true; + } + else + _pEnvironment->DeleteLocalRef( jThrow ); + return false; + } +} + + +void java_lang_Object::ThrowLoggedSQLException( const ::comphelper::EventLogger& _rLogger, JNIEnv* _pEnvironment, + const Reference< XInterface >& _rxContext ) +{ + SQLException aException; + if ( lcl_translateJNIExceptionToUNOException( _pEnvironment, _rxContext, aException ) ) + { + _rLogger.log( css::logging::LogLevel::SEVERE, STR_LOG_THROWING_EXCEPTION, aException.Message, aException.SQLState, aException.ErrorCode ); + throw aException; + } +} + +void java_lang_Object::ThrowSQLException( JNIEnv* _pEnvironment, const Reference< XInterface>& _rxContext ) +{ + SQLException aException; + if ( lcl_translateJNIExceptionToUNOException( _pEnvironment, _rxContext, aException ) ) + throw aException; +} + +void java_lang_Object::ThrowRuntimeException( JNIEnv* _pEnvironment, const Reference< XInterface>& _rxContext ) +{ + try + { + ThrowSQLException(_pEnvironment, _rxContext); + } + catch (const SQLException& e) + { + css::uno::Any anyEx = cppu::getCaughtException(); + throw css::lang::WrappedTargetRuntimeException( e.Message, + e.Context, anyEx ); + } +} + +void java_lang_Object::obtainMethodId_throwSQL(JNIEnv* _pEnv,const char* _pMethodName, const char* _pSignature,jmethodID& _inout_MethodID) const +{ + if ( !_inout_MethodID ) + { + _inout_MethodID = _pEnv->GetMethodID( getMyClass(), _pMethodName, _pSignature ); + OSL_ENSURE( _inout_MethodID, _pSignature ); + if ( !_inout_MethodID ) + throw SQLException(); + } // if ( !_inout_MethodID ) +} + +void java_lang_Object::obtainMethodId_throwRuntime(JNIEnv* _pEnv,const char* _pMethodName, const char* _pSignature,jmethodID& _inout_MethodID) const +{ + if ( !_inout_MethodID ) + { + _inout_MethodID = _pEnv->GetMethodID( getMyClass(), _pMethodName, _pSignature ); + OSL_ENSURE( _inout_MethodID, _pSignature ); + if ( !_inout_MethodID ) + throw RuntimeException(); + } // if ( !_inout_MethodID ) +} + + +bool java_lang_Object::callBooleanMethod( const char* _pMethodName, jmethodID& _inout_MethodID ) const +{ + bool out( false ); + + SDBThreadAttach t; + OSL_ENSURE( t.pEnv, "java_lang_Object::callBooleanMethod: no Java environment anymore!" ); + obtainMethodId_throwSQL(t.pEnv, _pMethodName,"()Z", _inout_MethodID); + // call method + out = t.pEnv->CallBooleanMethod( object, _inout_MethodID ); + ThrowSQLException( t.pEnv, nullptr ); + + return out; +} + +bool java_lang_Object::callBooleanMethodWithIntArg( const char* _pMethodName, jmethodID& _inout_MethodID, sal_Int32 _nArgument ) const +{ + bool out( false ); + SDBThreadAttach t; + OSL_ENSURE( t.pEnv, "java_lang_Object::callBooleanMethodWithIntArg: no Java environment anymore!" ); + obtainMethodId_throwSQL(t.pEnv, _pMethodName,"(I)Z", _inout_MethodID); + // call method + out = t.pEnv->CallBooleanMethod( object, _inout_MethodID, _nArgument ); + ThrowSQLException( t.pEnv, nullptr ); + + return out; +} + +jobject java_lang_Object::callResultSetMethod( JNIEnv& _rEnv,const char* _pMethodName, jmethodID& _inout_MethodID ) const +{ + // call method + jobject out = callObjectMethod(&_rEnv,_pMethodName,"()Ljava/sql/ResultSet;", _inout_MethodID); + return out; +} + +sal_Int32 java_lang_Object::callIntMethod_ThrowSQL(const char* _pMethodName, jmethodID& _inout_MethodID) const +{ + SDBThreadAttach t; + OSL_ENSURE( t.pEnv, "java_lang_Object::callIntMethod: no Java environment anymore!" ); + obtainMethodId_throwSQL(t.pEnv, _pMethodName,"()I", _inout_MethodID); + // call method + jint out( t.pEnv->CallIntMethod( object, _inout_MethodID ) ); + ThrowSQLException( t.pEnv, nullptr ); + return static_cast<sal_Int32>(out); +} + +sal_Int32 java_lang_Object::callIntMethod_ThrowRuntime(const char* _pMethodName, jmethodID& _inout_MethodID) const +{ + SDBThreadAttach t; + OSL_ENSURE( t.pEnv, "java_lang_Object::callIntMethod: no Java environment anymore!" ); + obtainMethodId_throwRuntime(t.pEnv, _pMethodName,"()I", _inout_MethodID); + // call method + jint out( t.pEnv->CallIntMethod( object, _inout_MethodID ) ); + ThrowRuntimeException(t.pEnv, nullptr); + return static_cast<sal_Int32>(out); +} + +sal_Int32 java_lang_Object::callIntMethodWithIntArg_ThrowSQL( const char* _pMethodName, jmethodID& _inout_MethodID,sal_Int32 _nArgument ) const +{ + SDBThreadAttach t; + OSL_ENSURE( t.pEnv, "java_lang_Object::callIntMethod: no Java environment anymore!" ); + obtainMethodId_throwSQL(t.pEnv, _pMethodName,"(I)I", _inout_MethodID); + // call method + jint out( t.pEnv->CallIntMethod( object, _inout_MethodID , _nArgument) ); + ThrowSQLException( t.pEnv, nullptr ); + return static_cast<sal_Int32>(out); +} + +sal_Int32 java_lang_Object::callIntMethodWithIntArg_ThrowRuntime( const char* _pMethodName, jmethodID& _inout_MethodID,sal_Int32 _nArgument ) const +{ + SDBThreadAttach t; + OSL_ENSURE( t.pEnv, "java_lang_Object::callIntMethod: no Java environment anymore!" ); + obtainMethodId_throwRuntime(t.pEnv, _pMethodName,"(I)I", _inout_MethodID); + // call method + jint out( t.pEnv->CallIntMethod( object, _inout_MethodID , _nArgument) ); + ThrowRuntimeException(t.pEnv, nullptr); + return static_cast<sal_Int32>(out); +} + +void java_lang_Object::callVoidMethod_ThrowSQL( const char* _pMethodName, jmethodID& _inout_MethodID) const +{ + SDBThreadAttach t; + OSL_ENSURE( t.pEnv, "java_lang_Object::callIntMethod: no Java environment anymore!" ); + obtainMethodId_throwSQL(t.pEnv, _pMethodName,"()V", _inout_MethodID); + + // call method + t.pEnv->CallVoidMethod( object, _inout_MethodID ); + ThrowSQLException( t.pEnv, nullptr ); +} + +void java_lang_Object::callVoidMethod_ThrowRuntime( const char* _pMethodName, jmethodID& _inout_MethodID) const +{ + SDBThreadAttach t; + OSL_ENSURE( t.pEnv, "java_lang_Object::callIntMethod: no Java environment anymore!" ); + obtainMethodId_throwRuntime(t.pEnv, _pMethodName,"()V", _inout_MethodID); + + // call method + t.pEnv->CallVoidMethod( object, _inout_MethodID ); + ThrowRuntimeException(t.pEnv, nullptr); +} + +void java_lang_Object::callVoidMethodWithIntArg_ThrowSQL( const char* _pMethodName, jmethodID& _inout_MethodID, sal_Int32 _nArgument ) const +{ + SDBThreadAttach t; + OSL_ENSURE( t.pEnv, "java_lang_Object::callIntMethod: no Java environment anymore!" ); + obtainMethodId_throwSQL(t.pEnv, _pMethodName,"(I)V", _inout_MethodID); + + // call method + t.pEnv->CallVoidMethod( object, _inout_MethodID,_nArgument ); + ThrowSQLException( t.pEnv, nullptr ); +} + +void java_lang_Object::callVoidMethodWithIntArg_ThrowRuntime( const char* _pMethodName, jmethodID& _inout_MethodID, sal_Int32 _nArgument ) const +{ + SDBThreadAttach t; + OSL_ENSURE( t.pEnv, "java_lang_Object::callIntMethod: no Java environment anymore!" ); + obtainMethodId_throwRuntime(t.pEnv, _pMethodName,"(I)V", _inout_MethodID); + + // call method + t.pEnv->CallVoidMethod( object, _inout_MethodID,_nArgument ); + ThrowRuntimeException(t.pEnv, nullptr); +} + +void java_lang_Object::callVoidMethodWithBoolArg_ThrowSQL( const char* _pMethodName, jmethodID& _inout_MethodID, bool _nArgument ) const +{ + SDBThreadAttach t; + OSL_ENSURE( t.pEnv, "java_lang_Object::callIntMethod: no Java environment anymore!" ); + obtainMethodId_throwSQL(t.pEnv, _pMethodName,"(Z)V", _inout_MethodID); + // call method + t.pEnv->CallVoidMethod( object, _inout_MethodID,int(_nArgument) ); + ThrowSQLException( t.pEnv, nullptr ); +} + +void java_lang_Object::callVoidMethodWithBoolArg_ThrowRuntime( const char* _pMethodName, jmethodID& _inout_MethodID, bool _nArgument ) const +{ + SDBThreadAttach t; + OSL_ENSURE( t.pEnv, "java_lang_Object::callIntMethod: no Java environment anymore!" ); + obtainMethodId_throwRuntime(t.pEnv, _pMethodName,"(Z)V", _inout_MethodID); + // call method + t.pEnv->CallVoidMethod( object, _inout_MethodID,int(_nArgument) ); + ThrowRuntimeException(t.pEnv, nullptr); +} + +OUString java_lang_Object::callStringMethod( const char* _pMethodName, jmethodID& _inout_MethodID ) const +{ + SDBThreadAttach t; + OSL_ENSURE( t.pEnv, "java_lang_Object::callStringMethod: no Java environment anymore!" ); + + // call method + jstring out = static_cast<jstring>(callObjectMethod(t.pEnv,_pMethodName,"()Ljava/lang/String;", _inout_MethodID)); + return JavaString2String( t.pEnv, out ); +} + +jobject java_lang_Object::callObjectMethod( JNIEnv * _pEnv,const char* _pMethodName,const char* _pSignature, jmethodID& _inout_MethodID ) const +{ + // obtain method ID + obtainMethodId_throwSQL(_pEnv, _pMethodName,_pSignature, _inout_MethodID); + // call method + jobject out = _pEnv->CallObjectMethod( object, _inout_MethodID); + ThrowSQLException( _pEnv, nullptr ); + return out; +} + + +jobject java_lang_Object::callObjectMethodWithIntArg( JNIEnv * _pEnv,const char* _pMethodName,const char* _pSignature, jmethodID& _inout_MethodID , sal_Int32 _nArgument) const +{ + obtainMethodId_throwSQL(_pEnv, _pMethodName,_pSignature, _inout_MethodID); + // call method + jobject out = _pEnv->CallObjectMethod( object, _inout_MethodID,_nArgument ); + ThrowSQLException( _pEnv, nullptr ); + return out; +} + +OUString java_lang_Object::callStringMethodWithIntArg( const char* _pMethodName, jmethodID& _inout_MethodID , sal_Int32 _nArgument) const +{ + SDBThreadAttach t; + OSL_ENSURE( t.pEnv, "java_lang_Object::callStringMethod: no Java environment anymore!" ); + jstring out = static_cast<jstring>(callObjectMethodWithIntArg(t.pEnv,_pMethodName,"(I)Ljava/lang/String;",_inout_MethodID,_nArgument)); + return JavaString2String( t.pEnv, out ); +} + +void java_lang_Object::callVoidMethodWithStringArg( const char* _pMethodName, jmethodID& _inout_MethodID,const OUString& _nArgument ) const +{ + SDBThreadAttach t; + OSL_ENSURE( t.pEnv, "java_lang_Object::callIntMethod: no Java environment anymore!" ); + obtainMethodId_throwSQL(t.pEnv, _pMethodName,"(Ljava/lang/String;)V", _inout_MethodID); + + jdbc::LocalRef< jstring > str( t.env(),convertwchar_tToJavaString(t.pEnv,_nArgument)); + // call method + t.pEnv->CallVoidMethod( object, _inout_MethodID , str.get()); + ThrowSQLException( t.pEnv, nullptr ); +} + +sal_Int32 java_lang_Object::callIntMethodWithStringArg( const char* _pMethodName, jmethodID& _inout_MethodID,const OUString& _nArgument ) const +{ + SDBThreadAttach t; + OSL_ENSURE( t.pEnv, "java_lang_Object::callIntMethodWithStringArg: no Java environment anymore!" ); + obtainMethodId_throwSQL(t.pEnv, _pMethodName,"(Ljava/lang/String;)I", _inout_MethodID); + + //TODO: Check if the code below is needed + //jdbc::LocalRef< jstring > str( t.env(), convertwchar_tToJavaString( t.pEnv, sql ) ); + //{ + // jdbc::ContextClassLoaderScope ccl( t.env(), + // m_pConnection ? m_pConnection->getDriverClassLoader() : jdbc::GlobalRef< jobject >(), + // m_aLogger, + // *this + // ); + + jdbc::LocalRef< jstring > str( t.env(),convertwchar_tToJavaString(t.pEnv,_nArgument)); + // call method + jint out = t.pEnv->CallIntMethod( object, _inout_MethodID , str.get()); + ThrowSQLException( t.pEnv, nullptr ); + return static_cast<sal_Int32>(out); +} + +jclass java_lang_Object::findMyClass(const char* _pClassName) +{ + // the class must be fetched only once, therefore static + SDBThreadAttach t; + jclass tempClass = t.pEnv->FindClass(_pClassName); OSL_ENSURE(tempClass,"Java : FindClass not successful!"); + if(!tempClass) + { + t.pEnv->ExceptionDescribe(); + t.pEnv->ExceptionClear(); + } + jclass globClass = static_cast<jclass>(t.pEnv->NewGlobalRef( tempClass )); + t.pEnv->DeleteLocalRef( tempClass ); + return globClass; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/PreparedStatement.cxx b/connectivity/source/drivers/jdbc/PreparedStatement.cxx new file mode 100644 index 000000000..34c28f084 --- /dev/null +++ b/connectivity/source/drivers/jdbc/PreparedStatement.cxx @@ -0,0 +1,697 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <java/sql/PreparedStatement.hxx> +#include <java/sql/ResultSet.hxx> +#include <java/sql/ResultSetMetaData.hxx> +#include <java/sql/Connection.hxx> +#include <java/sql/Timestamp.hxx> +#include <java/math/BigDecimal.hxx> +#include <java/tools.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <cppuhelper/queryinterface.hxx> +#include <comphelper/sequence.hxx> +#include <comphelper/types.hxx> +#include <connectivity/dbtools.hxx> +#include <connectivity/FValue.hxx> +#include <connectivity/dbexception.hxx> +#include <strings.hrc> +#include <resource/sharedresources.hxx> +#include <java/LocalRef.hxx> +#include <strings.hxx> +#include <string.h> +#include <memory> + +using namespace connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; + + +//************ Class: java.sql.PreparedStatement + +IMPLEMENT_SERVICE_INFO(java_sql_PreparedStatement,"com.sun.star.sdbcx.JPreparedStatement","com.sun.star.sdbc.PreparedStatement"); + +java_sql_PreparedStatement::java_sql_PreparedStatement( JNIEnv * pEnv, java_sql_Connection& _rCon, const OUString& sql ) + : OStatement_BASE2( pEnv, _rCon ) +{ + m_sSqlStatement = sql; +} + +jclass java_sql_PreparedStatement::theClass = nullptr; + +java_sql_PreparedStatement::~java_sql_PreparedStatement() +{ +} + + +jclass java_sql_PreparedStatement::getMyClass() const +{ + // the class must be fetched only once, therefore static + if( !theClass ) + theClass = findMyClass("java/sql/PreparedStatement"); + return theClass; +} + + +css::uno::Any SAL_CALL java_sql_PreparedStatement::queryInterface( const css::uno::Type & rType ) +{ + css::uno::Any aRet = OStatement_BASE2::queryInterface(rType); + return aRet.hasValue() ? aRet : ::cppu::queryInterface( rType, + static_cast< XPreparedStatement*>(this), + static_cast< XParameters*>(this), + static_cast< XResultSetMetaDataSupplier*>(this), + static_cast< XPreparedBatchExecution*>(this)); +} + +css::uno::Sequence< css::uno::Type > SAL_CALL java_sql_PreparedStatement::getTypes( ) +{ + ::cppu::OTypeCollection aTypes( cppu::UnoType<XPreparedStatement>::get(), + cppu::UnoType<XParameters>::get(), + cppu::UnoType<XResultSetMetaDataSupplier>::get(), + cppu::UnoType<XPreparedBatchExecution>::get()); + + return ::comphelper::concatSequences(aTypes.getTypes(),OStatement_BASE2::getTypes()); +} + + +sal_Bool SAL_CALL java_sql_PreparedStatement::execute( ) +{ + m_aLogger.log( LogLevel::FINE, STR_LOG_EXECUTING_PREPARED ); + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + return callBooleanMethod( "execute", mID ); +} + + +sal_Int32 SAL_CALL java_sql_PreparedStatement::executeUpdate( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + m_aLogger.log( LogLevel::FINE, STR_LOG_EXECUTING_PREPARED_UPDATE ); + + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + return callIntMethod_ThrowSQL("executeUpdate", mID); +} + + +void SAL_CALL java_sql_PreparedStatement::setString( sal_Int32 parameterIndex, const OUString& x ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + m_aLogger.log( LogLevel::FINER, STR_LOG_STRING_PARAMETER, parameterIndex, x ); + + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + { // initialize temporary Variable + createStatement(t.pEnv); + static const char * const cSignature = "(ILjava/lang/String;)V"; + static const char * const cMethodName = "setString"; + // Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + jdbc::LocalRef< jstring > str( t.env(),convertwchar_tToJavaString(t.pEnv,x)); + t.pEnv->CallVoidMethod( object, mID, parameterIndex,str.get()); + // and clean up + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + } //t.pEnv +} + + +css::uno::Reference< css::sdbc::XConnection > SAL_CALL java_sql_PreparedStatement::getConnection( ) +{ + return Reference< XConnection >(m_pConnection.get()); +} + + +css::uno::Reference< css::sdbc::XResultSet > SAL_CALL java_sql_PreparedStatement::executeQuery( ) +{ + m_aLogger.log( LogLevel::FINE, STR_LOG_EXECUTING_PREPARED_QUERY ); + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + jobject out = callResultSetMethod(t.env(),"executeQuery",mID); + + return out==nullptr ? nullptr : new java_sql_ResultSet( t.pEnv, out, m_aLogger, *m_pConnection,this); +} + + +void SAL_CALL java_sql_PreparedStatement::setBoolean( sal_Int32 parameterIndex, sal_Bool x ) +{ + m_aLogger.log( LogLevel::FINER, STR_LOG_BOOLEAN_PARAMETER, parameterIndex, bool(x) ); + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("setBoolean", "(IZ)V", mID, parameterIndex, x); +} + + +void SAL_CALL java_sql_PreparedStatement::setByte( sal_Int32 parameterIndex, sal_Int8 x ) +{ + m_aLogger.log( LogLevel::FINER, STR_LOG_BYTE_PARAMETER, parameterIndex, static_cast<sal_Int32>(x) ); + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("setByte", "(IB)V", mID, parameterIndex, x); +} + + +void SAL_CALL java_sql_PreparedStatement::setDate( sal_Int32 parameterIndex, const css::util::Date& x ) +{ + m_aLogger.log( LogLevel::FINER, STR_LOG_DATE_PARAMETER, parameterIndex, x ); + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + java_sql_Date aT(x); + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("setDate", "(ILjava/sql/Date;)V", mID, parameterIndex, aT.getJavaObject()); +} + + +void SAL_CALL java_sql_PreparedStatement::setTime( sal_Int32 parameterIndex, const css::util::Time& x ) +{ + m_aLogger.log( LogLevel::FINER, STR_LOG_TIME_PARAMETER, parameterIndex, x ); + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + java_sql_Time aT(x); + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("setTime", "(ILjava/sql/Time;)V", mID, parameterIndex, aT.getJavaObject()); +} + + +void SAL_CALL java_sql_PreparedStatement::setTimestamp( sal_Int32 parameterIndex, const css::util::DateTime& x ) +{ + m_aLogger.log( LogLevel::FINER, STR_LOG_TIMESTAMP_PARAMETER, parameterIndex, x ); + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + java_sql_Timestamp aD(x); + callVoidMethod_ThrowSQL("setTimestamp", "(ILjava/sql/Timestamp;)V", mID, parameterIndex, aD.getJavaObject()); +} + +void SAL_CALL java_sql_PreparedStatement::setDouble( sal_Int32 parameterIndex, double x ) +{ + m_aLogger.log( LogLevel::FINER, STR_LOG_DOUBLE_PARAMETER, parameterIndex, x ); + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("setDouble", "(ID)V", mID, parameterIndex, x); +} + + +void SAL_CALL java_sql_PreparedStatement::setFloat( sal_Int32 parameterIndex, float x ) +{ + m_aLogger.log( LogLevel::FINER, STR_LOG_FLOAT_PARAMETER, parameterIndex, x ); + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("setFloat", "(IF)V", mID, parameterIndex, x); +} + + +void SAL_CALL java_sql_PreparedStatement::setInt( sal_Int32 parameterIndex, sal_Int32 x ) +{ + m_aLogger.log( LogLevel::FINER, STR_LOG_INT_PARAMETER, parameterIndex, x ); + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("setInt", "(II)V", mID, parameterIndex, x); +} + + +void SAL_CALL java_sql_PreparedStatement::setLong( sal_Int32 parameterIndex, sal_Int64 x ) +{ + m_aLogger.log( LogLevel::FINER, STR_LOG_LONG_PARAMETER, parameterIndex, x ); + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("setLong", "(IJ)V", mID, parameterIndex, x); +} + + +void SAL_CALL java_sql_PreparedStatement::setNull( sal_Int32 parameterIndex, sal_Int32 sqlType ) +{ + m_aLogger.log( LogLevel::FINER, STR_LOG_NULL_PARAMETER, parameterIndex, sqlType ); + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("setNull", "(II)V", mID, parameterIndex, sqlType); +} + + +void SAL_CALL java_sql_PreparedStatement::setClob( sal_Int32 /*parameterIndex*/, const css::uno::Reference< css::sdbc::XClob >& /*x*/ ) +{ + ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setClob", *this ); +} + + +void SAL_CALL java_sql_PreparedStatement::setBlob( sal_Int32 /*parameterIndex*/, const css::uno::Reference< css::sdbc::XBlob >& /*x*/ ) +{ + ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setBlob", *this ); +} + + +void SAL_CALL java_sql_PreparedStatement::setArray( sal_Int32 /*parameterIndex*/, const css::uno::Reference< css::sdbc::XArray >& /*x*/ ) +{ + ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setArray", *this ); +} + + +void SAL_CALL java_sql_PreparedStatement::setRef( sal_Int32 /*parameterIndex*/, const css::uno::Reference< css::sdbc::XRef >& /*x*/ ) +{ + ::dbtools::throwFeatureNotImplementedSQLException( "XParameters::setRef", *this ); +} + + +void SAL_CALL java_sql_PreparedStatement::setObjectWithInfo( sal_Int32 parameterIndex, const css::uno::Any& x, sal_Int32 targetSqlType, sal_Int32 scale ) +{ + m_aLogger.log( LogLevel::FINER, STR_LOG_OBJECT_NULL_PARAMETER, parameterIndex ); + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + { + createStatement(t.pEnv); + + // initialize temporary Variable + static const char * const cSignature = "(ILjava/lang/Object;II)V"; + static const char * const cMethodName = "setObject"; + // Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + { + jobject obj = nullptr; + switch(targetSqlType) + { + case DataType::DECIMAL: + case DataType::NUMERIC: + { + double nTemp = 0.0; + + std::unique_ptr<java_math_BigDecimal> pBigDecimal; + if ( x >>= nTemp) + { + pBigDecimal.reset(new java_math_BigDecimal(nTemp)); + //setDouble(parameterIndex,nTemp); + //return; + } + else + { + ORowSetValue aValue; + aValue.fill(x); + const OUString sValue = aValue; + if ( !sValue.isEmpty() ) + pBigDecimal.reset(new java_math_BigDecimal(sValue)); + else + pBigDecimal.reset(new java_math_BigDecimal(0.0)); + } + //obj = convertwchar_tToJavaString(t.pEnv,::comphelper::getString(x)); + t.pEnv->CallVoidMethod( object, mID, parameterIndex,pBigDecimal->getJavaObject(),targetSqlType,scale); + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + return; + } + default: + obj = convertwchar_tToJavaString(t.pEnv,::comphelper::getString(x)); + break; + } + t.pEnv->CallVoidMethod( object, mID, parameterIndex,obj,targetSqlType,scale); + t.pEnv->DeleteLocalRef(obj); + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + // and clean up + } //mID + } //t.pEnv +} + + +void SAL_CALL java_sql_PreparedStatement::setObjectNull( sal_Int32 parameterIndex, sal_Int32 /*sqlType*/, const OUString& /*typeName*/ ) +{ + m_aLogger.log( LogLevel::FINER, STR_LOG_OBJECT_NULL_PARAMETER, parameterIndex ); + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL<jobject>("setObject", "(ILjava/lang/Object;)V", mID, parameterIndex, nullptr); +} + + +void SAL_CALL java_sql_PreparedStatement::setObject( sal_Int32 parameterIndex, const css::uno::Any& x ) +{ + if(!::dbtools::implSetObject(this,parameterIndex,x)) + { + const OUString sError( m_pConnection->getResources().getResourceStringWithSubstitution( + STR_UNKNOWN_PARA_TYPE, + "$position$", OUString::number(parameterIndex) + ) ); + ::dbtools::throwGenericSQLException(sError,*this); + } +} + + +void SAL_CALL java_sql_PreparedStatement::setShort( sal_Int32 parameterIndex, sal_Int16 x ) +{ + m_aLogger.log( LogLevel::FINER, STR_LOG_SHORT_PARAMETER, parameterIndex, x ); + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("setShort", "(IS)V", mID, parameterIndex, x); +} + + +void SAL_CALL java_sql_PreparedStatement::setBytes( sal_Int32 parameterIndex, const css::uno::Sequence< sal_Int8 >& x ) +{ + m_aLogger.log( LogLevel::FINER, STR_LOG_BYTES_PARAMETER, parameterIndex ); + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + { + createStatement(t.pEnv); + + // initialize temporary Variable + static const char * const cSignature = "(I[B)V"; + static const char * const cMethodName = "setBytes"; + // Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + jbyteArray pByteArray = t.pEnv->NewByteArray(x.getLength()); + jbyte * pData = reinterpret_cast<jbyte *>( + const_cast<sal_Int8 *>(x.getConstArray())); + // 4th param of Set*ArrayRegion changed from pointer to non-const to + // pointer to const between <http://docs.oracle.com/javase/6/docs/ + // technotes/guides/jni/spec/functions.html#wp22933> and + // <http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/ + // functions.html#wp22933>; work around that difference in a way + // that doesn't trigger loplugin:redundantcast + t.pEnv->SetByteArrayRegion(pByteArray,0,x.getLength(),pData); + t.pEnv->CallVoidMethod( object, mID, parameterIndex,pByteArray); + t.pEnv->DeleteLocalRef(pByteArray); + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + } //t.pEnv +} + + +void SAL_CALL java_sql_PreparedStatement::setCharacterStream( sal_Int32 parameterIndex, const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length ) +{ + m_aLogger.log( LogLevel::FINER, STR_LOG_CHARSTREAM_PARAMETER, parameterIndex ); + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + + SDBThreadAttach t; + assert(t.pEnv && "Java environment has been deleted!"); + { + createStatement(t.pEnv); + + // initialize temporary variable + static const char * const cSignature = "(ILjava/io/InputStream;I)V"; + static const char * const cMethodName = "setCharacterStream"; + // Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + Sequence< sal_Int8 > aSeq; + if ( x.is() ) + x->readBytes( aSeq, length ); + sal_Int32 actualLength = aSeq.getLength(); + + jvalue args2[3]; + jbyteArray pByteArray = t.pEnv->NewByteArray( actualLength ); + jbyte * aSeqData = reinterpret_cast<jbyte *>( + const_cast<sal_Int8 *>(aSeq.getConstArray())); + // 4th param of Set*ArrayRegion changed from pointer to non-const to + // pointer to const between <http://docs.oracle.com/javase/6/docs/ + // technotes/guides/jni/spec/functions.html#wp22933> and + // <http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/ + // functions.html#wp22933>; work around that difference in a way + // that doesn't trigger loplugin:redundantcast + t.pEnv->SetByteArrayRegion(pByteArray,0,actualLength,aSeqData); + args2[0].l = pByteArray; + args2[1].i = 0; + args2[2].i = actualLength; + // Java-Call + jclass aClass = t.pEnv->FindClass("java/io/CharArrayInputStream"); + static jmethodID mID2 = nullptr; + if ( !mID2 ) + { + // initialize temporary variable + const char * const cSignatureStream = "([BII)V"; + mID2 = t.pEnv->GetMethodID( aClass, "<init>", cSignatureStream ); + } + jobject tempObj = nullptr; + if(mID2) + tempObj = t.pEnv->NewObjectA( aClass, mID2, args2 ); + + t.pEnv->CallVoidMethod( object, mID, parameterIndex,tempObj,actualLength); + // and clean up + t.pEnv->DeleteLocalRef(pByteArray); + t.pEnv->DeleteLocalRef(tempObj); + t.pEnv->DeleteLocalRef(aClass); + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + } //t.pEnv +} + + +void SAL_CALL java_sql_PreparedStatement::setBinaryStream( sal_Int32 parameterIndex, const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length ) +{ + m_aLogger.log( LogLevel::FINER, STR_LOG_BINARYSTREAM_PARAMETER, parameterIndex ); + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + { + createStatement(t.pEnv); + // initialize temporary variable + static const char * const cSignature = "(ILjava/io/InputStream;I)V"; + static const char * const cMethodName = "setBinaryStream"; + // Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + { + Sequence< sal_Int8 > aSeq; + if ( x.is() ) + x->readBytes( aSeq, length ); + sal_Int32 actualLength = aSeq.getLength(); + + jvalue args2[3]; + jbyteArray pByteArray = t.pEnv->NewByteArray(actualLength); + jbyte * aSeqData = reinterpret_cast<jbyte *>( + const_cast<sal_Int8 *>(aSeq.getConstArray())); + // 4th param of Set*ArrayRegion changed from pointer to non-const to + // pointer to const between <http://docs.oracle.com/javase/6/docs/ + // technotes/guides/jni/spec/functions.html#wp22933> and + // <http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/ + // functions.html#wp22933>; work around that difference in a way + // that doesn't trigger loplugin:redundantcast + t.pEnv->SetByteArrayRegion(pByteArray,0,actualLength,aSeqData); + args2[0].l = pByteArray; + args2[1].i = 0; + args2[2].i = actualLength; + + // Java-Call + jclass aClass = t.pEnv->FindClass("java/io/ByteArrayInputStream"); + static jmethodID mID2 = nullptr; + if ( !mID2 ) + { + // initialize temporary variable + const char * const cSignatureStream = "([BII)V"; + mID2 = t.pEnv->GetMethodID( aClass, "<init>", cSignatureStream ); + } + jobject tempObj = nullptr; + if(mID2) + tempObj = t.pEnv->NewObjectA( aClass, mID2, args2 ); + t.pEnv->CallVoidMethod( object, mID, parameterIndex,tempObj,actualLength); + // and clean up + t.pEnv->DeleteLocalRef(pByteArray); + t.pEnv->DeleteLocalRef(tempObj); + t.pEnv->DeleteLocalRef(aClass); + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + } + } //t.pEnv +} + + +void SAL_CALL java_sql_PreparedStatement::clearParameters( ) +{ + m_aLogger.log( LogLevel::FINER, STR_LOG_CLEAR_PARAMETERS ); + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + + SDBThreadAttach t; + { + createStatement(t.pEnv); + + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("clearParameters",mID); + } //t.pEnv +} + +void SAL_CALL java_sql_PreparedStatement::clearBatch( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + { + createStatement(t.pEnv); + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("clearBatch",mID); + } //t.pEnv +} + + +void SAL_CALL java_sql_PreparedStatement::addBatch( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + { + createStatement(t.pEnv); + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("addBatch", mID); + } //t.pEnv +} + + +css::uno::Sequence< sal_Int32 > SAL_CALL java_sql_PreparedStatement::executeBatch( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + css::uno::Sequence< sal_Int32 > aSeq; + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + jintArray out = static_cast<jintArray>(callObjectMethod(t.pEnv,"executeBatch","()[I", mID)); + if(out) + { + jboolean p = false; + aSeq.realloc(t.pEnv->GetArrayLength(out)); + memcpy(aSeq.getArray(),t.pEnv->GetIntArrayElements(out,&p),aSeq.getLength()); + t.pEnv->DeleteLocalRef(out); + } + return aSeq; +} + +css::uno::Reference< css::sdbc::XResultSetMetaData > SAL_CALL java_sql_PreparedStatement::getMetaData( ) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + createStatement(t.pEnv); + static jmethodID mID(nullptr); + jobject out = callObjectMethod(t.pEnv,"getMetaData","()Ljava/sql/ResultSetMetaData;", mID); + + return out==nullptr ? nullptr : new java_sql_ResultSetMetaData( t.pEnv, out, *m_pConnection ); +} + +void SAL_CALL java_sql_PreparedStatement::acquire() throw() +{ + OStatement_BASE2::acquire(); +} + +void SAL_CALL java_sql_PreparedStatement::release() throw() +{ + OStatement_BASE2::release(); +} + +void java_sql_PreparedStatement::createStatement(JNIEnv* _pEnv) +{ + ::osl::MutexGuard aGuard( m_aMutex ); + checkDisposed(java_sql_Statement_BASE::rBHelper.bDisposed); + + if( !(!object && _pEnv) ) + return; + + // initialize temporary variable + static const char * const cMethodName = "prepareStatement"; + + jvalue args[1]; + // convert Parameter + args[0].l = convertwchar_tToJavaString(_pEnv,m_sSqlStatement); + // Java-Call + jobject out = nullptr; + static jmethodID mID(nullptr); + if ( !mID ) + { + static const char * const cSignature = "(Ljava/lang/String;II)Ljava/sql/PreparedStatement;"; + mID = _pEnv->GetMethodID( m_pConnection->getMyClass(), cMethodName, cSignature ); + } + if( mID ) + { + out = _pEnv->CallObjectMethod( m_pConnection->getJavaObject(), mID, args[0].l ,m_nResultSetType,m_nResultSetConcurrency); + } + else + { + static jmethodID mID2 = nullptr; + if ( !mID2 ) + { + static const char * const cSignature2 = "(Ljava/lang/String;)Ljava/sql/PreparedStatement;"; + mID2 = _pEnv->GetMethodID( m_pConnection->getMyClass(), cMethodName, cSignature2 ); + } + if ( mID2 ) + out = _pEnv->CallObjectMethod( m_pConnection->getJavaObject(), mID2, args[0].l ); + } + _pEnv->DeleteLocalRef(static_cast<jstring>(args[0].l)); + ThrowLoggedSQLException( m_aLogger, _pEnv, *this ); + if ( out ) + object = _pEnv->NewGlobalRef( out ); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/Reader.cxx b/connectivity/source/drivers/jdbc/Reader.cxx new file mode 100644 index 000000000..8dd12157e --- /dev/null +++ b/connectivity/source/drivers/jdbc/Reader.cxx @@ -0,0 +1,179 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <java/io/Reader.hxx> +#include <string.h> +#include <osl/diagnose.h> +using namespace connectivity; +using ::com::sun::star::uno::Sequence; + + +//************ Class: java.io.Reader + + +jclass java_io_Reader::theClass = nullptr; +java_io_Reader::java_io_Reader( JNIEnv * pEnv, jobject myObj ) + : java_lang_Object( pEnv, myObj ) +{ + SDBThreadAttach::addRef(); +} +java_io_Reader::~java_io_Reader() +{ + SDBThreadAttach::releaseRef(); +} + +jclass java_io_Reader::getMyClass() const +{ + // the class must be fetched only once, therefore static + if( !theClass ) + theClass = findMyClass("java/io/Reader"); + return theClass; +} + +sal_Int32 SAL_CALL java_io_Reader::readSomeBytes( css::uno::Sequence< sal_Int8 >& aData, sal_Int32 nMaxBytesToRead ) +{ + return readBytes(aData,nMaxBytesToRead); +} + +void SAL_CALL java_io_Reader::skipBytes( sal_Int32 nBytesToSkip ) +{ + static jmethodID mID(nullptr); + if(nBytesToSkip <= 0) + return; + + if(m_buf) + { + m_buf.reset(); + --nBytesToSkip; + } + + static_assert(sizeof(jchar) == 2, "I thought Java characters were UTF16 code units?"); + sal_Int32 nCharsToSkip = nBytesToSkip / sizeof(jchar); + callIntMethodWithIntArg_ThrowRuntime("skip",mID,nCharsToSkip); + if(nBytesToSkip % sizeof(jchar) != 0) + { + assert(nBytesToSkip % sizeof(jchar) == 1); + Sequence< sal_Int8 > aData(1); + assert(m_buf); + readBytes(aData, 1); + } +} + +sal_Int32 SAL_CALL java_io_Reader::available( ) +{ + if(m_buf) + return 1; + bool out; + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + + { + static const char * const cSignature = "()Z"; + static const char * const cMethodName = "ready"; + // Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwRuntime(t.pEnv, cMethodName,cSignature, mID); + out = t.pEnv->CallBooleanMethod( object, mID); + ThrowRuntimeException(t.pEnv,*this); + } //t.pEnv + return (m_buf ? 1 : 0) + (out ? 1 : 0); // no way to tell *how much* is ready +} + +void SAL_CALL java_io_Reader::closeInput( ) +{ + static jmethodID mID(nullptr); + callVoidMethod_ThrowRuntime("close", mID); +} + +sal_Int32 SAL_CALL java_io_Reader::readBytes( css::uno::Sequence< sal_Int8 >& aData, sal_Int32 nBytesToRead ) +{ + OSL_ENSURE(aData.getLength() >= nBytesToRead," Sequence is smaller than BytesToRead"); + + if(nBytesToRead == 0) + return 0; + + sal_Int8 *dst(aData.getArray()); + sal_Int32 nBytesWritten(0); + + if (m_buf) + { + if(!aData.hasElements()) + { + aData.realloc(1); + dst = aData.getArray(); + } + *dst = *m_buf; + m_buf.reset(); + ++nBytesWritten; + ++dst; + --nBytesToRead; + } + + if(nBytesToRead == 0) + return nBytesWritten; + + sal_Int32 nCharsToRead = (nBytesToRead + 1)/2; + + jint outChars(0); + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + + { + jcharArray pCharArray = t.pEnv->NewCharArray(nCharsToRead); + static const char * const cSignature = "([CII)I"; + static const char * const cMethodName = "read"; + // Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwRuntime(t.pEnv, cMethodName,cSignature, mID); + outChars = t.pEnv->CallIntMethod( object, mID, pCharArray, 0, nCharsToRead ); + if ( !outChars ) + { + if(nBytesWritten==0) + ThrowRuntimeException(t.pEnv,*this); + else + return 1; + } + if(outChars > 0) + { + static_assert(sizeof(jchar) == 2, "I thought Java characters were UTF16 code units?"); + const sal_Int32 jcs = sizeof(jchar); + const sal_Int32 outBytes = std::min(nBytesToRead, outChars*jcs); + assert(outBytes == outChars*jcs || outBytes == outChars*jcs - 1); + + jboolean p = JNI_FALSE; + if(aData.getLength() < nBytesWritten + outBytes) + { + aData.realloc(nBytesWritten + outBytes); + dst = aData.getArray() + nBytesWritten; + } + jchar *outBuf(t.pEnv->GetCharArrayElements(pCharArray,&p)); + + memcpy(dst, outBuf, outBytes); + nBytesWritten += outBytes; + if(outBytes < outChars*jcs) + { + assert(outChars*jcs - outBytes == 1); + assert(!m_buf); + m_buf = reinterpret_cast<char*>(outBuf)[outBytes]; + } + } + t.pEnv->DeleteLocalRef(pCharArray); + } //t.pEnv + return nBytesWritten; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/Ref.cxx b/connectivity/source/drivers/jdbc/Ref.cxx new file mode 100644 index 000000000..ca8e2e112 --- /dev/null +++ b/connectivity/source/drivers/jdbc/Ref.cxx @@ -0,0 +1,52 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <java/sql/Ref.hxx> + +using namespace connectivity; + +//************ Class: java.sql.Ref + + +jclass java_sql_Ref::theClass = nullptr; +java_sql_Ref::java_sql_Ref( JNIEnv * pEnv, jobject myObj ) +: java_lang_Object( pEnv, myObj ) +{ + SDBThreadAttach::addRef(); +} +java_sql_Ref::~java_sql_Ref() +{ + SDBThreadAttach::releaseRef(); +} + +jclass java_sql_Ref::getMyClass() const +{ + // the class must be fetched only once, therefore static + if( !theClass ) + theClass = findMyClass("java/sql/Ref"); + return theClass; +} + +OUString SAL_CALL java_sql_Ref::getBaseTypeName( ) +{ + static jmethodID mID(nullptr); + return callStringMethod("getBaseTypeName",mID); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/ResultSet.cxx b/connectivity/source/drivers/jdbc/ResultSet.cxx new file mode 100644 index 000000000..238e78702 --- /dev/null +++ b/connectivity/source/drivers/jdbc/ResultSet.cxx @@ -0,0 +1,998 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <java/lang/String.hxx> +#include <java/lang/Boolean.hxx> +#include <java/sql/ResultSet.hxx> +#include <java/math/BigDecimal.hxx> +#include <java/sql/JStatement.hxx> +#include <java/sql/SQLWarning.hxx> +#include <java/sql/Timestamp.hxx> +#include <java/sql/Array.hxx> +#include <java/sql/Ref.hxx> +#include <java/sql/Clob.hxx> +#include <java/sql/Blob.hxx> +#include <java/sql/ResultSetMetaData.hxx> +#include <java/io/InputStream.hxx> +#include <java/io/Reader.hxx> +#include <java/tools.hxx> +#include <comphelper/property.hxx> +#include <connectivity/CommonTools.hxx> +#include <cppuhelper/typeprovider.hxx> +#include <cppuhelper/exc_hlp.hxx> +#include <comphelper/sequence.hxx> +#include <com/sun/star/beans/PropertyAttribute.hpp> +#include <TConnection.hxx> +#include <comphelper/types.hxx> +#include <connectivity/dbtools.hxx> +#include <connectivity/dbexception.hxx> +#include <strings.hrc> +#include <resource/sharedresources.hxx> +#include <java/LocalRef.hxx> + +#include <string.h> +#include <memory> + +using namespace ::comphelper; + +using namespace connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; + +IMPLEMENT_SERVICE_INFO(java_sql_ResultSet,"com.sun.star.sdbcx.JResultSet","com.sun.star.sdbc.ResultSet"); + +//************ Class: java.sql.ResultSet + + +jclass java_sql_ResultSet::theClass = nullptr; +java_sql_ResultSet::java_sql_ResultSet( JNIEnv * pEnv, jobject myObj, const java::sql::ConnectionLog& _rParentLogger,java_sql_Connection& _rConnection, java_sql_Statement_Base* pStmt) + :java_sql_ResultSet_BASE(m_aMutex) + ,java_lang_Object( pEnv, myObj ) + ,OPropertySetHelper(java_sql_ResultSet_BASE::rBHelper) + ,m_aLogger( _rParentLogger, java::sql::ConnectionLog::RESULTSET ) + ,m_pConnection(&_rConnection) +{ + SDBThreadAttach::addRef(); + osl_atomic_increment(&m_refCount); + if ( pStmt ) + m_xStatement = *pStmt; + + osl_atomic_decrement(&m_refCount); +} + +java_sql_ResultSet::~java_sql_ResultSet() +{ + if ( !java_sql_ResultSet_BASE::rBHelper.bDisposed && !java_sql_ResultSet_BASE::rBHelper.bInDispose ) + { + // increment ref count to prevent double call of Dtor + osl_atomic_increment( &m_refCount ); + dispose(); + } +} + +jclass java_sql_ResultSet::getMyClass() const +{ + // the class must be fetched only once, therefore static + if( !theClass ) + theClass = findMyClass("java/sql/ResultSet"); + return theClass; +} + +void java_sql_ResultSet::disposing() +{ + OPropertySetHelper::disposing(); + + ::osl::MutexGuard aGuard(m_aMutex); + if( object ) + { + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("close", mID); + clearObject(*t.pEnv); + } + + SDBThreadAttach::releaseRef(); +} + +css::uno::Any SAL_CALL java_sql_ResultSet::queryInterface( const css::uno::Type & rType ) +{ + css::uno::Any aRet = OPropertySetHelper::queryInterface(rType); + return aRet.hasValue() ? aRet : java_sql_ResultSet_BASE::queryInterface(rType); +} + +css::uno::Sequence< css::uno::Type > SAL_CALL java_sql_ResultSet::getTypes( ) +{ + ::cppu::OTypeCollection aTypes( cppu::UnoType<css::beans::XMultiPropertySet>::get(), + cppu::UnoType<css::beans::XFastPropertySet>::get(), + cppu::UnoType<css::beans::XPropertySet>::get()); + + return ::comphelper::concatSequences(aTypes.getTypes(),java_sql_ResultSet_BASE::getTypes()); +} + + +sal_Int32 SAL_CALL java_sql_ResultSet::findColumn( const OUString& columnName ) +{ + static jmethodID mID(nullptr); + return callIntMethodWithStringArg("findColumn",mID,columnName); +} + +Reference< css::io::XInputStream > SAL_CALL java_sql_ResultSet::getBinaryStream( sal_Int32 columnIndex ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + static jmethodID mID(nullptr); + jobject out = callObjectMethodWithIntArg(t.pEnv,"getBinaryStream","(I)Ljava/io/InputStream;", mID, columnIndex); + + // WARNING: the caller becomes the owner of the returned pointer + return out==nullptr ? nullptr : new java_io_InputStream( t.pEnv, out ); +} + +Reference< css::io::XInputStream > SAL_CALL java_sql_ResultSet::getCharacterStream( sal_Int32 columnIndex ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + static jmethodID mID(nullptr); + jobject out = callObjectMethodWithIntArg(t.pEnv,"getCharacterStream","(I)Ljava/io/Reader;", mID, columnIndex); + + // WARNING: the caller becomes the owner of the returned pointer + return out==nullptr ? nullptr : new java_io_Reader( t.pEnv, out ); +} + + +sal_Bool SAL_CALL java_sql_ResultSet::getBoolean( sal_Int32 columnIndex ) +{ + static jmethodID mID(nullptr); + return callBooleanMethodWithIntArg( "getBoolean", mID,columnIndex ); +} + + +sal_Int8 SAL_CALL java_sql_ResultSet::getByte( sal_Int32 columnIndex ) +{ + static jmethodID mID(nullptr); + jbyte (JNIEnv::* const pCallMethod)( jobject obj, jmethodID methodID, ... ) = &JNIEnv::CallByteMethod; + return callMethodWithIntArg<jbyte>(pCallMethod,"getByte","(I)B",mID,columnIndex); +} + + +Sequence< sal_Int8 > SAL_CALL java_sql_ResultSet::getBytes( sal_Int32 columnIndex ) +{ + Sequence< sal_Int8 > aSeq; + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + static jmethodID mID(nullptr); + jbyteArray out = static_cast<jbyteArray>(callObjectMethodWithIntArg(t.pEnv,"getBytes","(I)[B", mID, columnIndex)); + if (out) + { + jboolean p = false; + aSeq.realloc(t.pEnv->GetArrayLength(out)); + memcpy(aSeq.getArray(),t.pEnv->GetByteArrayElements(out,&p),aSeq.getLength()); + t.pEnv->DeleteLocalRef(out); + } + return aSeq; +} + + +css::util::Date SAL_CALL java_sql_ResultSet::getDate( sal_Int32 columnIndex ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + static jmethodID mID(nullptr); + jobject out = callObjectMethodWithIntArg(t.pEnv,"getDate","(I)Ljava/sql/Date;", mID, columnIndex); + // WARNING: the caller becomes the owner of the returned pointer + return out ? static_cast <css::util::Date> (java_sql_Date( t.pEnv, out )) : css::util::Date(); +} + + +double SAL_CALL java_sql_ResultSet::getDouble( sal_Int32 columnIndex ) +{ + static jmethodID mID(nullptr); + jdouble (JNIEnv::* const pCallMethod)( jobject obj, jmethodID methodID, ... ) = &JNIEnv::CallDoubleMethod; + return callMethodWithIntArg<double>(pCallMethod,"getDouble","(I)D",mID,columnIndex); +} + + +float SAL_CALL java_sql_ResultSet::getFloat( sal_Int32 columnIndex ) +{ + static jmethodID mID(nullptr); + jfloat (JNIEnv::* const pCallMethod)( jobject obj, jmethodID methodID, ... ) = &JNIEnv::CallFloatMethod; + return callMethodWithIntArg<jfloat>(pCallMethod,"getFloat","(I)F",mID,columnIndex); +} + + +sal_Int32 SAL_CALL java_sql_ResultSet::getInt( sal_Int32 columnIndex ) +{ + static jmethodID mID(nullptr); + return callIntMethodWithIntArg_ThrowSQL("getInt",mID,columnIndex); +} + + +sal_Int32 SAL_CALL java_sql_ResultSet::getRow( ) +{ + static jmethodID mID(nullptr); + return callIntMethod_ThrowSQL("getRow", mID); +} + + +sal_Int64 SAL_CALL java_sql_ResultSet::getLong( sal_Int32 columnIndex ) +{ + static jmethodID mID(nullptr); + jlong (JNIEnv::* const pCallMethod)( jobject obj, jmethodID methodID, ... ) = &JNIEnv::CallLongMethod; + return callMethodWithIntArg<jlong>(pCallMethod,"getLong","(I)J",mID,columnIndex); +} + + +css::uno::Reference< css::sdbc::XResultSetMetaData > SAL_CALL java_sql_ResultSet::getMetaData( ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + static jmethodID mID(nullptr); + jobject out = callObjectMethod(t.pEnv,"getMetaData","()Ljava/sql/ResultSetMetaData;", mID); + + return out==nullptr ? nullptr : new java_sql_ResultSetMetaData( t.pEnv, out, *m_pConnection ); +} + +Reference< XArray > SAL_CALL java_sql_ResultSet::getArray( sal_Int32 columnIndex ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + static jmethodID mID(nullptr); + jobject out = callObjectMethodWithIntArg(t.pEnv,"getArray","(I)Ljava/sql/Array;", mID, columnIndex); + + // WARNING: the caller becomes the owner of the returned pointer + return out==nullptr ? nullptr : new java_sql_Array( t.pEnv, out ); +} + + +Reference< XClob > SAL_CALL java_sql_ResultSet::getClob( sal_Int32 columnIndex ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + static jmethodID mID(nullptr); + jobject out = callObjectMethodWithIntArg(t.pEnv,"getClob","(I)Ljava/sql/Clob;", mID, columnIndex); + // WARNING: the caller becomes the owner of the returned pointer + return out==nullptr ? nullptr : new java_sql_Clob( t.pEnv, out ); +} + +Reference< XBlob > SAL_CALL java_sql_ResultSet::getBlob( sal_Int32 columnIndex ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + static jmethodID mID(nullptr); + jobject out = callObjectMethodWithIntArg(t.pEnv,"getBlob","(I)Ljava/sql/Blob;", mID, columnIndex); + // WARNING: the caller becomes the owner of the returned pointer + return out==nullptr ? nullptr : new java_sql_Blob( t.pEnv, out ); +} + + +Reference< XRef > SAL_CALL java_sql_ResultSet::getRef( sal_Int32 columnIndex ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + static jmethodID mID(nullptr); + jobject out = callObjectMethodWithIntArg(t.pEnv,"getRef","(I)Ljava/sql/Ref;", mID, columnIndex); + + // WARNING: the caller becomes the owner of the returned pointer + return out==nullptr ? nullptr : new java_sql_Ref( t.pEnv, out ); +} + + +Any SAL_CALL java_sql_ResultSet::getObject( sal_Int32 columnIndex, const Reference< css::container::XNameAccess >& typeMap ) +{ + jobject out(nullptr); + Any aRet; + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + { + jvalue args[2]; + // convert parameter + args[0].i = columnIndex; + args[1].l = convertTypeMapToJavaMap(typeMap); + // initialize temporary Variable + // Java-Call + static jmethodID mID(nullptr); + if ( !mID ) + { + static const char * const cSignature = "(I)Ljava/lang/Object;"; + static const char * const cMethodName = "getObject"; + + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + } + + out = t.pEnv->CallObjectMethodA( object, mID, args); + t.pEnv->DeleteLocalRef(static_cast<jstring>(args[1].l)); + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + // and clean up + if ( out ) + { + if ( t.pEnv->IsInstanceOf(out,java_lang_String::st_getMyClass()) ) + { + java_lang_String aVal(t.pEnv,out); + aRet <<= OUString(aVal); + } + else if ( t.pEnv->IsInstanceOf(out,java_lang_Boolean::st_getMyClass()) ) + { + java_lang_Boolean aVal(t.pEnv,out); + static jmethodID methodID = nullptr; + aRet <<= aVal.callBooleanMethod("booleanValue",methodID); + } + else if ( t.pEnv->IsInstanceOf(out,java_sql_Date::st_getMyClass()) ) + { + java_sql_Date aVal(t.pEnv,out); + aRet <<= css::util::Date(aVal); + } + else if ( t.pEnv->IsInstanceOf(out,java_sql_Time::st_getMyClass()) ) + { + java_sql_Time aVal(t.pEnv,out); + aRet <<= css::util::Time(aVal); + } + else if ( t.pEnv->IsInstanceOf(out,java_sql_Timestamp::st_getMyClass()) ) + { + java_sql_Timestamp aVal(t.pEnv,out); + aRet <<= css::util::DateTime(aVal); + } + else + t.pEnv->DeleteLocalRef(out); + } + } //t.pEnv + return aRet; +} + + +sal_Int16 SAL_CALL java_sql_ResultSet::getShort( sal_Int32 columnIndex ) +{ + static jmethodID mID(nullptr); + jshort (JNIEnv::* const pCallMethod)( jobject obj, jmethodID methodID, ... ) = &JNIEnv::CallShortMethod; + return callMethodWithIntArg<jshort>(pCallMethod,"getShort","(I)S",mID,columnIndex); +} + + +OUString SAL_CALL java_sql_ResultSet::getString( sal_Int32 columnIndex ) +{ + static jmethodID mID(nullptr); + return callStringMethodWithIntArg("getString",mID,columnIndex); +} + + +css::util::Time SAL_CALL java_sql_ResultSet::getTime( sal_Int32 columnIndex ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + static jmethodID mID(nullptr); + jobject out = callObjectMethodWithIntArg(t.pEnv,"getTime","(I)Ljava/sql/Time;", mID, columnIndex); + // WARNING: the caller becomes the owner of the returned pointer + return out ? static_cast <css::util::Time> (java_sql_Time( t.pEnv, out )) : css::util::Time(); +} + + +css::util::DateTime SAL_CALL java_sql_ResultSet::getTimestamp( sal_Int32 columnIndex ) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + static jmethodID mID(nullptr); + jobject out = callObjectMethodWithIntArg(t.pEnv,"getTimestamp","(I)Ljava/sql/Timestamp;", mID, columnIndex); + // WARNING: the caller becomes the owner of the returned pointer + return out ? static_cast <css::util::DateTime> (java_sql_Timestamp( t.pEnv, out )) : css::util::DateTime(); +} + + +sal_Bool SAL_CALL java_sql_ResultSet::isAfterLast( ) +{ + static jmethodID mID(nullptr); + return callBooleanMethod( "isAfterLast", mID ); +} + +sal_Bool SAL_CALL java_sql_ResultSet::isFirst( ) +{ + static jmethodID mID(nullptr); + return callBooleanMethod( "isFirst", mID ); +} + +sal_Bool SAL_CALL java_sql_ResultSet::isLast( ) +{ + static jmethodID mID(nullptr); + return callBooleanMethod( "isLast", mID ); +} + +void SAL_CALL java_sql_ResultSet::beforeFirst( ) +{ + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("beforeFirst", mID); +} + +void SAL_CALL java_sql_ResultSet::afterLast( ) +{ + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("afterLast", mID); +} + + +void SAL_CALL java_sql_ResultSet::close( ) +{ + dispose(); +} + + +sal_Bool SAL_CALL java_sql_ResultSet::first( ) +{ + static jmethodID mID(nullptr); + return callBooleanMethod( "first", mID ); +} + + +sal_Bool SAL_CALL java_sql_ResultSet::last( ) +{ + static jmethodID mID(nullptr); + return callBooleanMethod( "last", mID ); +} + +sal_Bool SAL_CALL java_sql_ResultSet::absolute( sal_Int32 row ) +{ + static jmethodID mID(nullptr); + return callBooleanMethodWithIntArg( "absolute", mID,row ); +} + +sal_Bool SAL_CALL java_sql_ResultSet::relative( sal_Int32 row ) +{ + static jmethodID mID(nullptr); + return callBooleanMethodWithIntArg( "relative", mID,row ); +} + +sal_Bool SAL_CALL java_sql_ResultSet::previous( ) +{ + static jmethodID mID(nullptr); + return callBooleanMethod( "previous", mID ); +} + +Reference< XInterface > SAL_CALL java_sql_ResultSet::getStatement( ) +{ + return m_xStatement; +} + + +sal_Bool SAL_CALL java_sql_ResultSet::rowDeleted( ) +{ + static jmethodID mID(nullptr); + return callBooleanMethod( "rowDeleted", mID ); +} + +sal_Bool SAL_CALL java_sql_ResultSet::rowInserted( ) +{ + static jmethodID mID(nullptr); + return callBooleanMethod( "rowInserted", mID ); +} + +sal_Bool SAL_CALL java_sql_ResultSet::rowUpdated( ) +{ + static jmethodID mID(nullptr); + return callBooleanMethod( "rowUpdated", mID ); +} + + +sal_Bool SAL_CALL java_sql_ResultSet::isBeforeFirst( ) +{ + static jmethodID mID(nullptr); + return callBooleanMethod( "isBeforeFirst", mID ); +} + + +sal_Bool SAL_CALL java_sql_ResultSet::next( ) +{ + static jmethodID mID(nullptr); + return callBooleanMethod( "next", mID ); +} + +sal_Bool SAL_CALL java_sql_ResultSet::wasNull( ) +{ + static jmethodID mID(nullptr); + return callBooleanMethod( "wasNull", mID ); +} + +void SAL_CALL java_sql_ResultSet::cancel( ) +{ + static jmethodID mID(nullptr); + callVoidMethod_ThrowRuntime("cancel", mID); +} + +void SAL_CALL java_sql_ResultSet::clearWarnings( ) +{ + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("clearWarnings", mID); +} + +css::uno::Any SAL_CALL java_sql_ResultSet::getWarnings( ) +{ + SDBThreadAttach t; + static jmethodID mID(nullptr); + jobject out = callObjectMethod(t.pEnv,"getWarnings","()Ljava/sql/SQLWarning;", mID); + // WARNING: the caller becomes the owner of the returned pointer + if( out ) + { + java_sql_SQLWarning_BASE warn_base( t.pEnv, out ); + return makeAny( + static_cast< css::sdbc::SQLException >( + java_sql_SQLWarning(warn_base,*this))); + } + + return css::uno::Any(); +} + + +void SAL_CALL java_sql_ResultSet::insertRow( ) +{ + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("insertRow", mID); +} + +void SAL_CALL java_sql_ResultSet::updateRow( ) +{ + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("updateRow", mID); +} + +void SAL_CALL java_sql_ResultSet::deleteRow( ) +{ + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("deleteRow", mID); +} + + +void SAL_CALL java_sql_ResultSet::cancelRowUpdates( ) +{ + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("cancelRowUpdates", mID); +} + + +void SAL_CALL java_sql_ResultSet::moveToInsertRow( ) +{ + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("moveToInsertRow", mID); +} + + +void SAL_CALL java_sql_ResultSet::moveToCurrentRow( ) +{ + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("moveToCurrentRow", mID); +} + + +void SAL_CALL java_sql_ResultSet::updateNull( sal_Int32 columnIndex ) +{ + static jmethodID mID(nullptr); + callVoidMethodWithIntArg_ThrowSQL("updateNull", mID, columnIndex); +} + + +void SAL_CALL java_sql_ResultSet::updateBoolean( sal_Int32 columnIndex, sal_Bool x ) +{ + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("updateBoolean", "(IZ)V", mID, columnIndex, x); +} + +void SAL_CALL java_sql_ResultSet::updateByte( sal_Int32 columnIndex, sal_Int8 x ) +{ + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("updateByte", "(IB)V", mID, columnIndex, x); +} + + +void SAL_CALL java_sql_ResultSet::updateShort( sal_Int32 columnIndex, sal_Int16 x ) +{ + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("updateShort", "(IS)V", mID, columnIndex, x); +} + +void SAL_CALL java_sql_ResultSet::updateInt( sal_Int32 columnIndex, sal_Int32 x ) +{ + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("updateInt", "(II)V", mID, columnIndex, x); +} + +void SAL_CALL java_sql_ResultSet::updateLong( sal_Int32 columnIndex, sal_Int64 x ) +{ + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("updateLong", "(IJ)V", mID, columnIndex, x); +} + + +void SAL_CALL java_sql_ResultSet::updateFloat( sal_Int32 columnIndex, float x ) +{ + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("updateFloat", "(IF)V", mID, columnIndex, x); +} + + +void SAL_CALL java_sql_ResultSet::updateDouble( sal_Int32 columnIndex, double x ) +{ + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("updateDouble", "(ID)V", mID, columnIndex, x); +} + + +void SAL_CALL java_sql_ResultSet::updateString( sal_Int32 columnIndex, const OUString& x ) +{ + SDBThreadAttach t; + + { + // initialize temporary variable + // Java-Call + static jmethodID mID(nullptr); + if ( !mID ) + { + static const char * const cSignature = "(ILjava/lang/String;)V"; + static const char * const cMethodName = "updateString"; + + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + } + + { + // convert parameter + jdbc::LocalRef< jstring > str( t.env(),convertwchar_tToJavaString(t.pEnv,x)); + t.pEnv->CallVoidMethod( object, mID,columnIndex,str.get()); + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + } + } +} + + +void SAL_CALL java_sql_ResultSet::updateBytes( sal_Int32 columnIndex, const css::uno::Sequence< sal_Int8 >& x ) +{ + SDBThreadAttach t; + + { + // initialize temporary variable + // Java-Call + static jmethodID mID(nullptr); + if ( !mID ) + { + static const char * const cSignature = "(I[B)V"; + static const char * const cMethodName = "updateBytes"; + + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + } + + { + jbyteArray aArray = t.pEnv->NewByteArray(x.getLength()); + jbyte * pData = reinterpret_cast<jbyte *>( + const_cast<sal_Int8 *>(x.getConstArray())); + // 4th param of Set*ArrayRegion changed from pointer to non-const to + // pointer to const between <http://docs.oracle.com/javase/6/docs/ + // technotes/guides/jni/spec/functions.html#wp22933> and + // <http://docs.oracle.com/javase/7/docs/technotes/guides/jni/spec/ + // functions.html#wp22933>; work around that difference in a way + // that doesn't trigger loplugin:redundantcast + t.pEnv->SetByteArrayRegion(aArray,0,x.getLength(),pData); + // convert parameter + t.pEnv->CallVoidMethod( object, mID,columnIndex,aArray); + t.pEnv->DeleteLocalRef(aArray); + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + } + } +} + + +void SAL_CALL java_sql_ResultSet::updateDate( sal_Int32 columnIndex, const css::util::Date& x ) +{ + java_sql_Date aD(x); + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("updateDate", "(ILjava/sql/Date;)V", mID, columnIndex, aD.getJavaObject()); +} + + +void SAL_CALL java_sql_ResultSet::updateTime( sal_Int32 columnIndex, const css::util::Time& x ) +{ + java_sql_Time aD(x); + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("updateTime", "(ILjava/sql/Time;)V", mID, columnIndex, aD.getJavaObject()); +} + + +void SAL_CALL java_sql_ResultSet::updateTimestamp( sal_Int32 columnIndex, const css::util::DateTime& x ) +{ + java_sql_Timestamp aD(x); + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("updateTimestamp", "(ILjava/sql/Timestamp;)V", mID, columnIndex, aD.getJavaObject()); +} + + +void SAL_CALL java_sql_ResultSet::updateBinaryStream( sal_Int32 columnIndex, const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length ) +{ + try + { + SDBThreadAttach t; + { + + // initialize temporary variable + // Java-Call + static jmethodID mID(nullptr); + if ( !mID ) + { + static const char * const cSignature = "(ILjava/io/InputStream;I)V"; + static const char * const cMethodName = "updateBinaryStream"; + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + } + + { + // convert Parameter + jobject obj = createByteInputStream(x,length); + t.pEnv->CallVoidMethod( object, mID, columnIndex,obj,length); + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + } + } + } + catch(const Exception&) + { + Any anyEx = ::cppu::getCaughtException(); + ::dbtools::throwFeatureNotImplementedSQLException( "XRowUpdate::updateBinaryStream", *this, anyEx ); + } +} + +void SAL_CALL java_sql_ResultSet::updateCharacterStream( sal_Int32 columnIndex, const css::uno::Reference< css::io::XInputStream >& x, sal_Int32 length ) +{ + try + { + SDBThreadAttach t; + { + + // initialize temporary variable + // Java-Call + static jmethodID mID(nullptr); + if ( !mID ) + { + static const char * const cSignature = "(ILjava/io/Reader;I)V"; + static const char * const cMethodName = "updateCharacterStream"; + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + } + + { + // convert Parameter + jobject obj = createCharArrayReader(x,length); + t.pEnv->CallVoidMethod( object, mID, columnIndex,obj,length); + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + } + } + } + catch(const Exception&) + { + Any anyEx = ::cppu::getCaughtException(); + ::dbtools::throwFeatureNotImplementedSQLException( "XRowUpdate::updateCharacterStream", *this, anyEx ); + } +} + +void SAL_CALL java_sql_ResultSet::updateObject( sal_Int32 columnIndex, const css::uno::Any& x ) +{ + if(!::dbtools::implUpdateObject(this,columnIndex,x)) + { + ::connectivity::SharedResources aResources; + const OUString sError( aResources.getResourceStringWithSubstitution( + STR_UNKNOWN_COLUMN_TYPE, + "$position$", OUString::number(columnIndex) + ) ); + ::dbtools::throwGenericSQLException(sError,*this); + } +} + + +void SAL_CALL java_sql_ResultSet::updateNumericObject( sal_Int32 columnIndex, const css::uno::Any& x, sal_Int32 scale ) +{ + // OSL_FAIL("java_sql_ResultSet::updateNumericObject: NYI"); + try + { + SDBThreadAttach t; + + { + + // initialize temporary variable + // Java-Call + static jmethodID mID(nullptr); + if ( !mID ) + { + static const char * const cSignature = "(ILjava/lang/Object;I)V"; + static const char * const cMethodName = "updateObject"; + + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + } + + { + // convert parameter + double nTemp = 0.0; + std::unique_ptr<java_math_BigDecimal> pBigDecimal; + if ( x >>= nTemp) + { + pBigDecimal.reset(new java_math_BigDecimal(nTemp)); + } + else + pBigDecimal.reset(new java_math_BigDecimal(::comphelper::getString(x))); + + t.pEnv->CallVoidMethod( object, mID, columnIndex,pBigDecimal->getJavaObject(),scale); + ThrowLoggedSQLException( m_aLogger, t.pEnv, *this ); + } + } + } + catch(const Exception&) + { + updateObject( columnIndex,x); + } +} + +sal_Int32 java_sql_ResultSet::getResultSetConcurrency() const +{ + static jmethodID mID(nullptr); + return callIntMethod_ThrowRuntime("getConcurrency", mID); +} + +sal_Int32 java_sql_ResultSet::getResultSetType() const +{ + static jmethodID mID(nullptr); + return callIntMethod_ThrowRuntime("getType",mID); +} + +sal_Int32 java_sql_ResultSet::getFetchDirection() const +{ + static jmethodID mID(nullptr); + return callIntMethod_ThrowRuntime("getFetchDirection", mID); +} + +sal_Int32 java_sql_ResultSet::getFetchSize() const +{ + static jmethodID mID(nullptr); + return callIntMethod_ThrowRuntime("getFetchSize", mID); +} + +OUString java_sql_ResultSet::getCursorName() const +{ + static jmethodID mID(nullptr); + return callStringMethod("getCursorName",mID); +} + + +void java_sql_ResultSet::setFetchDirection(sal_Int32 _par0) +{ + static jmethodID mID(nullptr); + callVoidMethodWithIntArg_ThrowRuntime("setFetchDirection", mID, _par0); +} + +void SAL_CALL java_sql_ResultSet::refreshRow( ) +{ + static jmethodID mID(nullptr); + callVoidMethod_ThrowSQL("refreshRow",mID); +} + +void java_sql_ResultSet::setFetchSize(sal_Int32 _par0) +{ + static jmethodID mID(nullptr); + callVoidMethodWithIntArg_ThrowRuntime("setFetchSize", mID, _par0); +} + +::cppu::IPropertyArrayHelper* java_sql_ResultSet::createArrayHelper( ) const +{ + Sequence< Property > aProps(5); + Property* pProperties = aProps.getArray(); + sal_Int32 nPos = 0; + pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_CURSORNAME), + PROPERTY_ID_CURSORNAME, cppu::UnoType<OUString>::get(), PropertyAttribute::READONLY); + + pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHDIRECTION), + PROPERTY_ID_FETCHDIRECTION, cppu::UnoType<sal_Int32>::get(), 0); + + pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_FETCHSIZE), + PROPERTY_ID_FETCHSIZE, cppu::UnoType<sal_Int32>::get(), 0); + + pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETCONCURRENCY), + PROPERTY_ID_RESULTSETCONCURRENCY, cppu::UnoType<sal_Int32>::get(), PropertyAttribute::READONLY); + + pProperties[nPos++] = css::beans::Property(::connectivity::OMetaConnection::getPropMap().getNameByIndex(PROPERTY_ID_RESULTSETTYPE), + PROPERTY_ID_RESULTSETTYPE, cppu::UnoType<sal_Int32>::get(), PropertyAttribute::READONLY); + + return new ::cppu::OPropertyArrayHelper(aProps); +} + +::cppu::IPropertyArrayHelper & java_sql_ResultSet::getInfoHelper() +{ + return *getArrayHelper(); +} + +sal_Bool java_sql_ResultSet::convertFastPropertyValue( + css::uno::Any & rConvertedValue, + css::uno::Any & rOldValue, + sal_Int32 nHandle, + const css::uno::Any& rValue ) +{ + bool bRet = false; + switch(nHandle) + { + case PROPERTY_ID_CURSORNAME: + case PROPERTY_ID_RESULTSETCONCURRENCY: + case PROPERTY_ID_RESULTSETTYPE: + throw css::lang::IllegalArgumentException(); + case PROPERTY_ID_FETCHDIRECTION: + bRet = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getFetchDirection()); + break; + case PROPERTY_ID_FETCHSIZE: + bRet = ::comphelper::tryPropertyValue(rConvertedValue, rOldValue, rValue, getFetchSize()); + break; + default: + break; + } + return bRet; +} + + +void java_sql_ResultSet::setFastPropertyValue_NoBroadcast( + sal_Int32 nHandle, + const css::uno::Any& rValue + ) +{ + switch(nHandle) + { + case PROPERTY_ID_CURSORNAME: + case PROPERTY_ID_RESULTSETCONCURRENCY: + case PROPERTY_ID_RESULTSETTYPE: + throw css::uno::Exception("cannot set prop " + OUString::number(nHandle), nullptr); + case PROPERTY_ID_FETCHDIRECTION: + setFetchDirection(comphelper::getINT32(rValue)); + break; + case PROPERTY_ID_FETCHSIZE: + setFetchSize(comphelper::getINT32(rValue)); + break; + default: + ; + } +} + +void java_sql_ResultSet::getFastPropertyValue( + css::uno::Any& rValue, + sal_Int32 nHandle + ) const +{ + try + { + switch(nHandle) + { + case PROPERTY_ID_CURSORNAME: + rValue <<= getCursorName(); + break; + case PROPERTY_ID_RESULTSETCONCURRENCY: + rValue <<= getResultSetConcurrency(); + break; + case PROPERTY_ID_RESULTSETTYPE: + rValue <<= getResultSetType(); + break; + case PROPERTY_ID_FETCHDIRECTION: + rValue <<= getFetchDirection(); + break; + case PROPERTY_ID_FETCHSIZE: + rValue <<= getFetchSize(); + break; + } + } + catch(const Exception&) + { + } +} + +void SAL_CALL java_sql_ResultSet::acquire() throw() +{ + java_sql_ResultSet_BASE::acquire(); +} + +void SAL_CALL java_sql_ResultSet::release() throw() +{ + java_sql_ResultSet_BASE::release(); +} + +css::uno::Reference< css::beans::XPropertySetInfo > SAL_CALL java_sql_ResultSet::getPropertySetInfo( ) +{ + return ::cppu::OPropertySetHelper::createPropertySetInfo(getInfoHelper()); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/ResultSetMetaData.cxx b/connectivity/source/drivers/jdbc/ResultSetMetaData.cxx new file mode 100644 index 000000000..fdf5bfe69 --- /dev/null +++ b/connectivity/source/drivers/jdbc/ResultSetMetaData.cxx @@ -0,0 +1,200 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <java/sql/ResultSetMetaData.hxx> +#include <java/sql/Connection.hxx> + +using namespace connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; + + +//************ Class: java.sql.ResultSetMetaData + + +jclass java_sql_ResultSetMetaData::theClass = nullptr; +java_sql_ResultSetMetaData::java_sql_ResultSetMetaData( JNIEnv * pEnv, jobject myObj, java_sql_Connection& _rCon ) + :java_lang_Object( pEnv, myObj ) + ,m_pConnection( &_rCon ) + ,m_nColumnCount(-1) +{ + SDBThreadAttach::addRef(); +} +java_sql_ResultSetMetaData::~java_sql_ResultSetMetaData() +{ + SDBThreadAttach::releaseRef(); +} + +jclass java_sql_ResultSetMetaData::getMyClass() const +{ + // The class needs to be fetched just once, that is why it is static + if( !theClass ) + theClass = findMyClass("java/sql/ResultSetMetaData"); + return theClass; +} + + +sal_Int32 SAL_CALL java_sql_ResultSetMetaData::getColumnDisplaySize( sal_Int32 column ) +{ + static jmethodID mID(nullptr); + return callIntMethodWithIntArg_ThrowSQL("getColumnDisplaySize",mID,column); +} + + +sal_Int32 SAL_CALL java_sql_ResultSetMetaData::getColumnType( sal_Int32 column ) +{ + static jmethodID mID(nullptr); + return callIntMethodWithIntArg_ThrowSQL("getColumnType",mID,column); +} + + +sal_Int32 SAL_CALL java_sql_ResultSetMetaData::getColumnCount( ) +{ + if ( m_nColumnCount == -1 ) + { + static jmethodID mID(nullptr); + m_nColumnCount = callIntMethod_ThrowSQL("getColumnCount", mID); + } // if ( m_nColumnCount == -1 ) + return m_nColumnCount; + +} + + +sal_Bool SAL_CALL java_sql_ResultSetMetaData::isCaseSensitive( sal_Int32 column ) +{ + static jmethodID mID(nullptr); + return callBooleanMethodWithIntArg( "isCaseSensitive", mID,column ); +} + +OUString SAL_CALL java_sql_ResultSetMetaData::getSchemaName( sal_Int32 column ) +{ + static jmethodID mID(nullptr); + return callStringMethodWithIntArg("getSchemaName",mID,column); +} + + +OUString SAL_CALL java_sql_ResultSetMetaData::getColumnName( sal_Int32 column ) +{ + static jmethodID mID(nullptr); + return callStringMethodWithIntArg("getColumnName",mID,column); +} + +OUString SAL_CALL java_sql_ResultSetMetaData::getTableName( sal_Int32 column ) +{ + static jmethodID mID(nullptr); + return callStringMethodWithIntArg("getTableName",mID,column); +} + +OUString SAL_CALL java_sql_ResultSetMetaData::getCatalogName( sal_Int32 column ) +{ + static jmethodID mID(nullptr); + return callStringMethodWithIntArg("getCatalogName",mID,column); +} + +OUString SAL_CALL java_sql_ResultSetMetaData::getColumnTypeName( sal_Int32 column ) +{ + static jmethodID mID(nullptr); + return callStringMethodWithIntArg("getColumnTypeName",mID,column); +} + +OUString SAL_CALL java_sql_ResultSetMetaData::getColumnLabel( sal_Int32 column ) +{ + static jmethodID mID(nullptr); + return callStringMethodWithIntArg("getColumnLabel",mID,column); +} + +OUString SAL_CALL java_sql_ResultSetMetaData::getColumnServiceName( sal_Int32 column ) +{ + static jmethodID mID(nullptr); + return callStringMethodWithIntArg("getColumnClassName",mID,column); +} + + +sal_Bool SAL_CALL java_sql_ResultSetMetaData::isCurrency( sal_Int32 column ) +{ + if ( m_pConnection->isIgnoreCurrencyEnabled() ) + return false; + static jmethodID mID(nullptr); + return callBooleanMethodWithIntArg( "isCurrency", mID,column ); +} + + +sal_Bool SAL_CALL java_sql_ResultSetMetaData::isAutoIncrement( sal_Int32 column ) +{ + static jmethodID mID(nullptr); + return callBooleanMethodWithIntArg( "isAutoIncrement", mID,column ); +} + + +sal_Bool SAL_CALL java_sql_ResultSetMetaData::isSigned( sal_Int32 column ) +{ + static jmethodID mID(nullptr); + return callBooleanMethodWithIntArg( "isSigned", mID,column ); +} + +sal_Int32 SAL_CALL java_sql_ResultSetMetaData::getPrecision( sal_Int32 column ) +{ + static jmethodID mID(nullptr); + return callIntMethodWithIntArg_ThrowSQL("getPrecision",mID,column); +} + +sal_Int32 SAL_CALL java_sql_ResultSetMetaData::getScale( sal_Int32 column ) +{ + static jmethodID mID(nullptr); + return callIntMethodWithIntArg_ThrowSQL("getScale",mID,column); +} + +sal_Int32 SAL_CALL java_sql_ResultSetMetaData::isNullable( sal_Int32 column ) +{ + static jmethodID mID(nullptr); + return callIntMethodWithIntArg_ThrowSQL("isNullable",mID,column); +} + + +sal_Bool SAL_CALL java_sql_ResultSetMetaData::isSearchable( sal_Int32 column ) +{ + static jmethodID mID(nullptr); + return callBooleanMethodWithIntArg( "isSearchable", mID,column ); +} + + +sal_Bool SAL_CALL java_sql_ResultSetMetaData::isReadOnly( sal_Int32 column ) +{ + static jmethodID mID(nullptr); + return callBooleanMethodWithIntArg( "isReadOnly", mID,column ); +} + + +sal_Bool SAL_CALL java_sql_ResultSetMetaData::isDefinitelyWritable( sal_Int32 column ) +{ + static jmethodID mID(nullptr); + return callBooleanMethodWithIntArg( "isDefinitelyWritable", mID,column ); +} + +sal_Bool SAL_CALL java_sql_ResultSetMetaData::isWritable( sal_Int32 column ) +{ + static jmethodID mID(nullptr); + return callBooleanMethodWithIntArg( "isWritable", mID,column ); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/SQLException.cxx b/connectivity/source/drivers/jdbc/SQLException.cxx new file mode 100644 index 000000000..55bf0996c --- /dev/null +++ b/connectivity/source/drivers/jdbc/SQLException.cxx @@ -0,0 +1,87 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <java/sql/SQLException.hxx> + +using namespace connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::lang; + +//************ Class: java.sql.SQLException + +java_sql_SQLException::java_sql_SQLException( const java_sql_SQLException_BASE& _rException,const Reference< XInterface> & _rContext) + : css::sdbc::SQLException( _rException.getMessage(), + _rContext, + _rException.getSQLState(), + _rException.getErrorCode(), + makeAny(_rException.getNextException()) + ) +{ +} + +java_sql_SQLException_BASE::java_sql_SQLException_BASE( JNIEnv * pEnv, jobject myObj ) : java_lang_Exception( pEnv, myObj ) +{ +} + +jclass java_sql_SQLException_BASE::theClass = nullptr; + +java_sql_SQLException_BASE::~java_sql_SQLException_BASE() +{} + + +jclass java_sql_SQLException_BASE::getMyClass() const +{ + return st_getMyClass(); +} +jclass java_sql_SQLException_BASE::st_getMyClass() +{ + // The class needs to be fetched just once, that is why it is static + if( !theClass ) + theClass = findMyClass("java/sql/SQLException"); + return theClass; +} + +css::sdbc::SQLException java_sql_SQLException_BASE::getNextException() const +{ + SDBThreadAttach t; + static jmethodID mID(nullptr); + jobject out = callObjectMethod(t.pEnv,"getNextException","()Ljava/sql/SQLException;", mID); + // WARNING: the caller will become the owner of the returned pointers !!! + if( out ) + { + java_sql_SQLException_BASE warn_base(t.pEnv,out); + return css::sdbc::SQLException(java_sql_SQLException(warn_base,nullptr)); + } + + return css::sdbc::SQLException(); +} + +OUString java_sql_SQLException_BASE::getSQLState() const +{ + static jmethodID mID(nullptr); + return callStringMethod("getSQLState",mID); +} +sal_Int32 java_sql_SQLException_BASE::getErrorCode() const +{ + static jmethodID mID(nullptr); + return callIntMethod_ThrowSQL("getErrorCode", mID); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/SQLWarning.cxx b/connectivity/source/drivers/jdbc/SQLWarning.cxx new file mode 100644 index 000000000..16616d18b --- /dev/null +++ b/connectivity/source/drivers/jdbc/SQLWarning.cxx @@ -0,0 +1,39 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <java/sql/SQLWarning.hxx> +using namespace connectivity; + +//************ Class: java.sql.SQLWarning + + +jclass java_sql_SQLWarning_BASE::theClass = nullptr; + +java_sql_SQLWarning_BASE::~java_sql_SQLWarning_BASE() +{} + +jclass java_sql_SQLWarning_BASE::getMyClass() const +{ + // the class needs to be fetched only once, that is why it is static + if( !theClass ) + theClass = findMyClass("java/sql/SQLWarning"); + return theClass; +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/String.cxx b/connectivity/source/drivers/jdbc/String.cxx new file mode 100644 index 000000000..f7e682c02 --- /dev/null +++ b/connectivity/source/drivers/jdbc/String.cxx @@ -0,0 +1,53 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <java/lang/String.hxx> +#include <java/tools.hxx> +using namespace connectivity; + +//************ Class: java.lang.String + + +jclass java_lang_String::theClass = nullptr; + +java_lang_String::~java_lang_String() +{} + +jclass java_lang_String::getMyClass() const +{ + return st_getMyClass(); +} +jclass java_lang_String::st_getMyClass() +{ + // the class needs to be fetched only once, that is why it is static + if( !theClass ) + theClass = findMyClass("java/lang/String"); + return theClass; +} + + +java_lang_String::operator OUString() +{ + SDBThreadAttach t; + if(!t.pEnv) + return OUString(); + return JavaString2String(t.pEnv, static_cast<jstring>(object)); +} + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/Throwable.cxx b/connectivity/source/drivers/jdbc/Throwable.cxx new file mode 100644 index 000000000..c96f5532f --- /dev/null +++ b/connectivity/source/drivers/jdbc/Throwable.cxx @@ -0,0 +1,66 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <java/lang/Throwable.hxx> + +using namespace connectivity; + +//************ Class: java.lang.Throwable + + +jclass java_lang_Throwable::theClass = nullptr; + +java_lang_Throwable::~java_lang_Throwable() +{} + +jclass java_lang_Throwable::getMyClass() const +{ + return st_getMyClass(); +} +jclass java_lang_Throwable::st_getMyClass() +{ + // the class needs to be fetched only once, that is why it is static + if( !theClass ) + theClass = findMyClass("java/lang/Throwable"); + return theClass; +} + + +OUString java_lang_Throwable::getMessage() const +{ + static jmethodID mID(nullptr); + return callStringMethod("getMessage",mID); +} + + +OUString java_lang_Throwable::getLocalizedMessage() const +{ + static jmethodID mID(nullptr); + return callStringMethod("getLocalizedMessage",mID); +} + +#if OSL_DEBUG_LEVEL > 0 +void java_lang_Throwable::printStackTrace() const +{ + static jmethodID mID(nullptr); + return callVoidMethod_ThrowSQL("printStackTrace",mID); +} +#endif + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/Timestamp.cxx b/connectivity/source/drivers/jdbc/Timestamp.cxx new file mode 100644 index 000000000..eb7624719 --- /dev/null +++ b/connectivity/source/drivers/jdbc/Timestamp.cxx @@ -0,0 +1,189 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <java/sql/Timestamp.hxx> +#include <java/tools.hxx> +#include <connectivity/dbconversion.hxx> +#include <osl/diagnose.h> + +using namespace ::comphelper; +using namespace connectivity; + +//************ Class: java.sql.Date + + +jclass java_sql_Date::theClass = nullptr; +java_sql_Date::java_sql_Date( const css::util::Date& _rOut ) : java_util_Date( nullptr, nullptr ) +{ + SDBThreadAttach t; + if( !t.pEnv ) + return; + jvalue args[1]; + // Convert parameters + OUString sDateStr = ::dbtools::DBTypeConversion::toDateString(_rOut); + args[0].l = convertwchar_tToJavaString(t.pEnv,sDateStr); + + // Turn of Java-Call for the constructor + // initialise temporary variables + jobject tempObj; + static jmethodID mID(nullptr); + if ( !mID ) + { + static const char * const cSignature = "(Ljava/lang/String;)Ljava/sql/Date;"; + mID = t.pEnv->GetStaticMethodID( getMyClass(), "valueOf", cSignature ); + } + OSL_ENSURE(mID,"Unknown method id!"); + tempObj = t.pEnv->CallStaticObjectMethod( getMyClass(), mID, args[0].l ); + saveRef( t.pEnv, tempObj ); + t.pEnv->DeleteLocalRef( tempObj ); + // and clean +} + +java_sql_Date::~java_sql_Date() +{} + +jclass java_sql_Date::getMyClass() const +{ + return st_getMyClass(); +} +jclass java_sql_Date::st_getMyClass() +{ + // the class needs only be fetched once, that is why it is static + if( !theClass ) + theClass = findMyClass("java/sql/Date"); + return theClass; +} + + +java_sql_Date::operator css::util::Date() +{ + return ::dbtools::DBTypeConversion::toDate(toString()); +} + + +//************ Class: java.sql.Time + + +jclass java_sql_Time::theClass = nullptr; + +java_sql_Time::~java_sql_Time() +{} + +jclass java_sql_Time::getMyClass() const +{ + return st_getMyClass(); +} +jclass java_sql_Time::st_getMyClass() +{ + // the class needs only be fetched once, that is why it is static + if( !theClass ) + theClass = findMyClass("java/sql/Time"); + return theClass; +} +java_sql_Time::java_sql_Time( const css::util::Time& _rOut ): java_util_Date( nullptr, nullptr ) +{ + SDBThreadAttach t; + if( !t.pEnv ) + return; + jvalue args[1]; + // Convert parameters + // java.sql.Time supports only whole seconds... + OUString sDateStr = ::dbtools::DBTypeConversion::toTimeStringS(_rOut); + args[0].l = convertwchar_tToJavaString(t.pEnv,sDateStr); + + // Turn off Java-Call for the constructor + // initialise temporary variables + jobject tempObj; + static jmethodID mID(nullptr); + if ( !mID ) + { + static const char * const cSignature = "(Ljava/lang/String;)Ljava/sql/Time;"; + mID = t.pEnv->GetStaticMethodID( getMyClass(), "valueOf", cSignature ); + } + OSL_ENSURE(mID,"Unknown method id!"); + tempObj = t.pEnv->CallStaticObjectMethod( getMyClass(), mID, args[0].l ); + t.pEnv->DeleteLocalRef(static_cast<jstring>(args[0].l)); + saveRef( t.pEnv, tempObj ); + t.pEnv->DeleteLocalRef( tempObj ); + // and clean +} + +java_sql_Time::operator css::util::Time() +{ + return ::dbtools::DBTypeConversion::toTime(toString()); +} + +//************ Class: java.sql.Timestamp + + +jclass java_sql_Timestamp::theClass = nullptr; + +java_sql_Timestamp::~java_sql_Timestamp() +{} + +jclass java_sql_Timestamp::getMyClass() const +{ + return st_getMyClass(); +} + +jclass java_sql_Timestamp::st_getMyClass() +{ + // the class needs only be fetched once, that is why it is static + if( !theClass ) + theClass = findMyClass("java/sql/Timestamp"); + return theClass; +} + +java_sql_Timestamp::java_sql_Timestamp(const css::util::DateTime& _rOut) + :java_util_Date( nullptr, nullptr ) +{ + SDBThreadAttach t; + if( !t.pEnv ) + return; + jvalue args[1]; + // Convert parameters + OUString sDateStr = ::dbtools::DBTypeConversion::toDateTimeString(_rOut); + + args[0].l = convertwchar_tToJavaString(t.pEnv,sDateStr); + + // Turn off Java-Call for the constructor + // initialise temporary variables + jobject tempObj; + static jmethodID mID(nullptr); + if ( !mID ) + { + static const char * const cSignature = "(Ljava/lang/String;)Ljava/sql/Timestamp;"; + mID = t.pEnv->GetStaticMethodID( getMyClass(), "valueOf", cSignature ); + } + OSL_ENSURE(mID,"Unknown method id!"); + tempObj = t.pEnv->CallStaticObjectMethod( getMyClass(), mID, args[0].l ); + + saveRef( t.pEnv, tempObj ); + t.pEnv->DeleteLocalRef( tempObj ); + // and clean +} + + +java_sql_Timestamp::operator css::util::DateTime() +{ + return ::dbtools::DBTypeConversion::toDateTime(toString()); +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/jdbc.component b/connectivity/source/drivers/jdbc/jdbc.component new file mode 100644 index 000000000..07fd03c68 --- /dev/null +++ b/connectivity/source/drivers/jdbc/jdbc.component @@ -0,0 +1,36 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + --> + +<!-- Recent Java 6 VMs make calls to JNI Attach/DetachCurrentThread (which this + code does extensively) very expensive. A follow-up JVM fix reduced the + overhead significantly again for all threads but the main thread. So a + quick hack to improve performance of this component again is to confine it + in the affine apartment (where all code will run on a single, dedicated + thread that is guaranteed no to be the main thread). However, a better fix + would still be to redesign the code so that it does not call + Attach/DetachCurrentThread so frequently: +--> + +<component loader="com.sun.star.loader.SharedLibrary" + environment="@CPPU_ENV@:affine" prefix="jdbc" + xmlns="http://openoffice.org/2010/uno-components"> + <implementation name="com.sun.star.comp.sdbc.JDBCDriver"> + <service name="com.sun.star.sdbc.Driver"/> + </implementation> +</component> diff --git a/connectivity/source/drivers/jdbc/jservices.cxx b/connectivity/source/drivers/jdbc/jservices.cxx new file mode 100644 index 000000000..63ae84c8e --- /dev/null +++ b/connectivity/source/drivers/jdbc/jservices.cxx @@ -0,0 +1,106 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + +#include <java/sql/Driver.hxx> +#include <cppuhelper/factory.hxx> +#include <com/sun/star/lang/XSingleServiceFactory.hpp> + +using namespace connectivity; +using ::com::sun::star::uno::Reference; +using ::com::sun::star::uno::Sequence; +using ::com::sun::star::lang::XSingleServiceFactory; +using ::com::sun::star::lang::XMultiServiceFactory; + +typedef Reference< XSingleServiceFactory > (*createFactoryFunc) + ( + const Reference< XMultiServiceFactory > & rServiceManager, + const OUString & rComponentName, + ::cppu::ComponentInstantiation pCreateFunction, + const Sequence< OUString > & rServiceNames, + rtl_ModuleCount* + ); + +namespace { + +struct ProviderRequest +{ + Reference< XSingleServiceFactory > xRet; + Reference< XMultiServiceFactory > const xServiceManager; + OUString const sImplementationName; + + ProviderRequest( + void* pServiceManager, + char const* pImplementationName + ) + : xServiceManager(static_cast<XMultiServiceFactory*>(pServiceManager)) + , sImplementationName(OUString::createFromAscii(pImplementationName)) + { + } + + bool CREATE_PROVIDER( + const OUString& Implname, + const Sequence< OUString > & Services, + ::cppu::ComponentInstantiation Factory, + createFactoryFunc creator + ) + { + if (!xRet.is() && (Implname == sImplementationName)) + { + try + { + xRet = creator( xServiceManager, sImplementationName,Factory, Services,nullptr); + } + catch(...) + { + } + } + return xRet.is(); + } + + void* getProvider() const { return xRet.get(); } +}; + +} + +extern "C" SAL_DLLPUBLIC_EXPORT void* jdbc_component_getFactory( + const char* pImplementationName, + void* pServiceManager, + void* /*pRegistryKey*/) +{ + void* pRet = nullptr; + if (pServiceManager) + { + ProviderRequest aReq(pServiceManager,pImplementationName); + + aReq.CREATE_PROVIDER( + java_sql_Driver::getImplementationName_Static(), + java_sql_Driver::getSupportedServiceNames_Static(), + java_sql_Driver_CreateInstance, + ::cppu::createSingleFactory); + + if(aReq.xRet.is()) + aReq.xRet->acquire(); + pRet = aReq.getProvider(); + } + + return pRet; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ diff --git a/connectivity/source/drivers/jdbc/tools.cxx b/connectivity/source/drivers/jdbc/tools.cxx new file mode 100644 index 000000000..5021d653a --- /dev/null +++ b/connectivity/source/drivers/jdbc/tools.cxx @@ -0,0 +1,262 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* + * This file is part of the LibreOffice project. + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. + * + * This file incorporates work covered by the following license notice: + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed + * with this work for additional information regarding copyright + * ownership. The ASF licenses this file to you under the Apache + * License, Version 2.0 (the "License"); you may not use this file + * except in compliance with the License. You may obtain a copy of + * the License at http://www.apache.org/licenses/LICENSE-2.0 . + */ + + +#include <string.h> +#include <java/tools.hxx> +#include <java/util/Property.hxx> +#include <com/sun/star/sdbc/DriverPropertyInfo.hpp> +#include <com/sun/star/sdbc/SQLException.hpp> +#include <com/sun/star/container/XNameAccess.hpp> +#include <connectivity/dbexception.hxx> +#include <osl/diagnose.h> + +using namespace connectivity; +using namespace ::com::sun::star::uno; +using namespace ::com::sun::star::beans; +using namespace ::com::sun::star::sdbc; +using namespace ::com::sun::star::container; +using namespace ::com::sun::star::lang; + +void java_util_Properties::setProperty(const OUString& key, const OUString& value) +{ + SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java environment has been deleted!"); + jobject out(nullptr); + + { + jvalue args[2]; + // Convert Parameter + args[0].l = convertwchar_tToJavaString(t.pEnv,key); + args[1].l = convertwchar_tToJavaString(t.pEnv,value); + // Initialize temporary Variables + static const char * const cSignature = "(Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Object;"; + static const char * const cMethodName = "setProperty"; + // Turn off Java-Call + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, cMethodName,cSignature, mID); + out = t.pEnv->CallObjectMethod(object, mID, args[0].l,args[1].l); + ThrowSQLException(t.pEnv,nullptr); + t.pEnv->DeleteLocalRef(static_cast<jstring>(args[1].l)); + t.pEnv->DeleteLocalRef(static_cast<jstring>(args[0].l)); + ThrowSQLException(t.pEnv,nullptr); + if(out) + t.pEnv->DeleteLocalRef(out); + } //t.pEnv + // WARNING: The caller will be owner of the returned pointers!!! +} +jclass java_util_Properties::theClass = nullptr; + +java_util_Properties::~java_util_Properties() +{} + +jclass java_util_Properties::getMyClass() const +{ + // the class needs only be called once, that is why it is static + if( !theClass ) + theClass = findMyClass("java/util/Properties"); + return theClass; +} + + +java_util_Properties::java_util_Properties( ): java_lang_Object( nullptr, nullptr ) +{ + SDBThreadAttach t; + if( !t.pEnv ) + return; + // Turn off Java-Call for the constructor + // Initialize temporary Variables + static const char * const cSignature = "()V"; + jobject tempObj; + static jmethodID mID(nullptr); + obtainMethodId_throwSQL(t.pEnv, "<init>",cSignature, mID); + tempObj = t.pEnv->NewObject( getMyClass(), mID); + saveRef( t.pEnv, tempObj ); + t.pEnv->DeleteLocalRef( tempObj ); +} + + +jstring connectivity::convertwchar_tToJavaString(JNIEnv *pEnv,const OUString& _rTemp) +{ + OSL_ENSURE(pEnv,"Environment is NULL!"); + jstring pStr = pEnv->NewString( + reinterpret_cast<jchar const *>(_rTemp.getStr()), _rTemp.getLength()); + pEnv->ExceptionClear(); + OSL_ENSURE(pStr,"Could not create a jsstring object!"); + return pStr; +} + + +std::unique_ptr<java_util_Properties> connectivity::createStringPropertyArray(const Sequence< PropertyValue >& info ) +{ + std::unique_ptr<java_util_Properties> pProps(new java_util_Properties()); + const PropertyValue* pBegin = info.getConstArray(); + const PropertyValue* pEnd = pBegin + info.getLength(); + + for(;pBegin != pEnd;++pBegin) + { + // these are properties used internally by LibreOffice, + // and should not be passed to the JDBC driver + // (which probably does not know anything about them anyway). + if ( pBegin->Name != "JavaDriverClass" + && pBegin->Name != "JavaDriverClassPath" + && pBegin->Name != "SystemProperties" + && pBegin->Name != "CharSet" + && pBegin->Name != "AppendTableAliasName" + && pBegin->Name != "AppendTableAliasInSelect" + && pBegin->Name != "DisplayVersionColumns" + && pBegin->Name != "GeneratedValues" + && pBegin->Name != "UseIndexDirectionKeyword" + && pBegin->Name != "UseKeywordAsBeforeAlias" + && pBegin->Name != "AddIndexAppendix" + && pBegin->Name != "FormsCheckRequiredFields" + && pBegin->Name != "GenerateASBeforeCorrelationName" + && pBegin->Name != "EscapeDateTime" + && pBegin->Name != "ParameterNameSubstitution" + && pBegin->Name != "IsPasswordRequired" + && pBegin->Name != "IsAutoRetrievingEnabled" + && pBegin->Name != "AutoRetrievingStatement" + && pBegin->Name != "UseCatalogInSelect" + && pBegin->Name != "UseSchemaInSelect" + && pBegin->Name != "AutoIncrementCreation" + && pBegin->Name != "Extension" + && pBegin->Name != "NoNameLengthLimit" + && pBegin->Name != "EnableSQL92Check" + && pBegin->Name != "EnableOuterJoinEscape" + && pBegin->Name != "BooleanComparisonMode" + && pBegin->Name != "IgnoreCurrency" + && pBegin->Name != "TypeInfoSettings" + && pBegin->Name != "IgnoreDriverPrivileges" + && pBegin->Name != "ImplicitCatalogRestriction" + && pBegin->Name != "ImplicitSchemaRestriction" + && pBegin->Name != "SupportsTableCreation" + && pBegin->Name != "UseJava" + && pBegin->Name != "Authentication" + && pBegin->Name != "PreferDosLikeLineEnds" + && pBegin->Name != "PrimaryKeySupport" + && pBegin->Name != "RespectDriverResultSetType" + ) + { + OUString aStr; + OSL_VERIFY( pBegin->Value >>= aStr ); + pProps->setProperty(pBegin->Name,aStr); + } + } + return pProps; +} + +OUString connectivity::JavaString2String(JNIEnv *pEnv,jstring Str) +{ + OUString aStr; + if(Str) + { + jboolean bCopy(true); + const jchar* pChar = pEnv->GetStringChars(Str,&bCopy); + jsize len = pEnv->GetStringLength(Str); + aStr = OUString(reinterpret_cast<sal_Unicode const *>(pChar), len); + + if(bCopy) + pEnv->ReleaseStringChars(Str,pChar); + pEnv->DeleteLocalRef(Str); + } + return aStr; +} + +jobject connectivity::convertTypeMapToJavaMap(const Reference< css::container::XNameAccess > & _rMap) +{ + if ( _rMap.is() ) + { + css::uno::Sequence< OUString > aNames = _rMap->getElementNames(); + if ( aNames.hasElements() ) + ::dbtools::throwFeatureNotImplementedSQLException( "Type maps", nullptr ); + } + return nullptr; +} + +bool connectivity::isExceptionOccurred(JNIEnv *pEnv) +{ + if ( !pEnv ) + return false; + + jthrowable pThrowable = pEnv->ExceptionOccurred(); + bool bRet = pThrowable != nullptr; + if ( pThrowable ) + { + pEnv->ExceptionClear(); + pEnv->DeleteLocalRef(pThrowable); + } + + return bRet; +} + +jobject connectivity::createByteInputStream(const css::uno::Reference< css::io::XInputStream >& x,sal_Int32 length) +{ + SDBThreadAttach t; + if( !t.pEnv || !x.is() ) + return nullptr; + // Turn off Java-Call for the constructor + // Initialize temporary variables + jclass clazz = java_lang_Object::findMyClass("java/io/ByteArrayInputStream"); + static jmethodID mID(nullptr); + if ( !mID ) + { + static const char * const cSignature = "([B)V"; + mID = t.pEnv->GetMethodID( clazz, "<init>", cSignature ); + OSL_ENSURE( mID, cSignature ); + if ( !mID ) + throw SQLException(); + } // if ( !_inout_MethodID ) + jbyteArray pByteArray = t.pEnv->NewByteArray(length); + Sequence< sal_Int8 > aData; + x->readBytes(aData,length); + jboolean p = false; + memcpy(t.pEnv->GetByteArrayElements(pByteArray,&p),aData.getArray(),aData.getLength()); + jobject out = t.pEnv->NewObject( clazz, mID,pByteArray); + t.pEnv->DeleteLocalRef(pByteArray); + return out; +} + +jobject connectivity::createCharArrayReader(const css::uno::Reference< css::io::XInputStream >& x,sal_Int32 length) +{ + SDBThreadAttach t; + if( !t.pEnv || !x.is() ) + return nullptr; + // Turn off Java-Call for the constructor + // Initialize temporary Variables + jclass clazz = java_lang_Object::findMyClass("java/io/CharArrayReader"); + static jmethodID mID(nullptr); + if ( !mID ) + { + static const char * const cSignature = "([C)V"; + mID = t.pEnv->GetMethodID( clazz, "<init>", cSignature ); + OSL_ENSURE( mID, cSignature ); + if ( !mID ) + throw SQLException(); + } // if ( !_inout_MethodID ) + jcharArray pCharArray = t.pEnv->NewCharArray(length); + Sequence< sal_Int8 > aData; + x->readBytes(aData,length); + jboolean p = false; + memcpy(t.pEnv->GetCharArrayElements(pCharArray,&p),aData.getArray(),aData.getLength()); + jobject out = t.pEnv->NewObject( clazz, mID,pCharArray); + t.pEnv->DeleteLocalRef(pCharArray); + return out; +} + + +/* vim:set shiftwidth=4 softtabstop=4 expandtab: */ |