summaryrefslogtreecommitdiff
path: root/connectivity/source/drivers/jdbc/JConnection.cxx
diff options
context:
space:
mode:
authorOliver Bolte <obo@openoffice.org>2007-03-12 09:41:12 +0000
committerOliver Bolte <obo@openoffice.org>2007-03-12 09:41:12 +0000
commitbb1625b3359ef1037f799bcf6009f1f1d12eb055 (patch)
treeb96d0d046d8925cec2475550f88a020164e559bb /connectivity/source/drivers/jdbc/JConnection.cxx
parentd203ce86a955c3f40c2a9c0e65d9e58d9b653ce1 (diff)
INTEGRATION: CWS sb36 (1.2.28); FILE MERGED
2007/03/05 16:52:53 sb 1.2.28.3: #i69624# Load each class only once. 2007/01/22 08:54:09 sb 1.2.28.2: RESYNC: (1.2-1.3); FILE MERGED 2007/01/16 14:30:15 sb 1.2.28.1: #i51803# Merged in Connection.cxx:1.22.60.5.
Diffstat (limited to 'connectivity/source/drivers/jdbc/JConnection.cxx')
-rw-r--r--connectivity/source/drivers/jdbc/JConnection.cxx204
1 files changed, 173 insertions, 31 deletions
diff --git a/connectivity/source/drivers/jdbc/JConnection.cxx b/connectivity/source/drivers/jdbc/JConnection.cxx
index d57fecf539e3..d53d313b4084 100644
--- a/connectivity/source/drivers/jdbc/JConnection.cxx
+++ b/connectivity/source/drivers/jdbc/JConnection.cxx
@@ -4,9 +4,9 @@
*
* $RCSfile: JConnection.cxx,v $
*
- * $Revision: 1.3 $
+ * $Revision: 1.4 $
*
- * last change: $Author: vg $ $Date: 2007-01-15 13:35:13 $
+ * last change: $Author: obo $ $Date: 2007-03-12 10:41:12 $
*
* The Contents of this file are made available subject to
* the terms of GNU Lesser General Public License Version 2.1.
@@ -70,6 +70,12 @@
#include "connectivity/dbexception.hxx"
#endif
#include "java/util/Property.hxx"
+#include "com/sun/star/uno/XComponentContext.hpp"
+#include "jvmaccess/classpath.hxx"
+
+#include <jni.h>
+
+#include <list>
#include <memory>
using namespace connectivity;
@@ -80,6 +86,109 @@ using namespace ::com::sun::star::sdbc;
using namespace ::com::sun::star::container;
using namespace ::com::sun::star::lang;
+namespace {
+
+struct JObject {
+ JObject(JNIEnv * environment): object(NULL), m_environment(environment) {}
+ ~JObject() { if (object != NULL) m_environment->DeleteLocalRef(object); }
+
+ jobject release() {
+ jobject t = object;
+ object = NULL;
+ return t;
+ }
+
+ jobject object;
+
+private:
+ JNIEnv *& m_environment;
+};
+
+struct ClassMapEntry {
+ ClassMapEntry(
+ rtl::OUString const & theClassPath, rtl::OUString const & theClassName):
+ classPath(theClassPath), className(theClassName), classObject(NULL) {}
+
+ rtl::OUString classPath;
+ rtl::OUString className;
+ jweak classObject;
+};
+
+typedef std::list< ClassMapEntry > ClassMap;
+
+struct ClassMapData {
+ osl::Mutex mutex;
+
+ ClassMap map;
+};
+
+struct ClassMapDataInit {
+ ClassMapData * operator()() {
+ static ClassMapData instance;
+ return &instance;
+ }
+};
+
+// Load a class (see jvmaccess::ClassPath::loadClass in jvmaccess/classpath.hxx
+// for details). A map from (classPath, name) pairs to weak Java class
+// references is maintained, so that a class is only loaded once. If null is
+// returned, a (still pending) JNI exception occurred.
+jclass loadClass(
+ Reference< XComponentContext > const & context, JNIEnv * environment,
+ rtl::OUString const & classPath, rtl::OUString const & name)
+{
+ // For any jweak entries still present in the map upon destruction,
+ // DeleteWeakGlobalRef is not called (which is a leak):
+ ClassMapData * d =
+ rtl_Instance< ClassMapData, ClassMapDataInit, osl::MutexGuard,
+ osl::GetGlobalMutex >::create(
+ ClassMapDataInit(), osl::GetGlobalMutex());
+ osl::MutexGuard g(d->mutex);
+ JObject cl(environment);
+ // Prune dangling weak references from the list while searching for a match,
+ // so that the list cannot grow unbounded:
+ for (ClassMap::iterator i(d->map.begin()); i != d->map.end();) {
+ JObject o(environment);
+ o.object = environment->NewLocalRef(i->classObject);
+ if (o.object == NULL) {
+ if (environment->ExceptionCheck()) {
+ return NULL;
+ }
+ if (i->classObject != NULL) {
+ environment->DeleteWeakGlobalRef(i->classObject);
+ }
+ i = d->map.erase(i);
+ } else {
+ if (i->classPath == classPath && i->className == name) {
+ cl.object = o.release();
+ }
+ ++i;
+ }
+ }
+ if (cl.object == NULL) {
+ // 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
+ // (jvmaccess::ClassPath::loadClass throws, return NULL, etc.) it will
+ // be pruned on next call because its classObject is null:
+ d->map.push_front(ClassMapEntry(classPath, name));
+ cl.object = jvmaccess::ClassPath::loadClass(
+ context, environment, classPath, name);
+ if (cl.object == NULL) {
+ return NULL;
+ }
+ jweak w = environment->NewWeakGlobalRef(cl.object);
+ if (w == NULL) {
+ return NULL;
+ }
+ d->map.front().classObject = w;
+ }
+ return static_cast< jclass >(cl.release());
+}
+
+}
+
//------------------------------------------------------------------------------
IMPLEMENT_SERVICE_INFO(java_sql_Connection,"com.sun.star.sdbcx.JConnection","com.sun.star.sdbc.Connection");
//------------------------------------------------------------------------------
@@ -690,40 +799,19 @@ void java_sql_Connection::loadDriverFromProperties(const Sequence< PropertyValue
SDBThreadAttach t; OSL_ENSURE(t.pEnv,"Java Enviroment geloescht worden!");
try
{
+ const PropertyValue* pJavaDriverClass = 0;
+ const PropertyValue* pJavaDriverClassPath = 0;
const PropertyValue* pBegin = info.getConstArray();
const PropertyValue* pEnd = pBegin + info.getLength();
for(;pBegin != pEnd;++pBegin)
{
- if ( !object && !pBegin->Name.compareToAscii("JavaDriverClass") )
+ if (!pBegin->Name.compareToAscii("JavaDriverClass"))
{
- // here I try to find the class for jdbc driver
- java_sql_SQLException_BASE::getMyClass();
- java_lang_Throwable::getMyClass();
-
- ::rtl::OUString aStr;
- OSL_VERIFY( pBegin->Value >>= aStr );
- OSL_ASSERT( aStr.getLength());
- if ( aStr.getLength() )
- {
- // the driver manager holds the class of the driver for later use
- // if forName didn't find the class it will throw an exception
- ::std::auto_ptr< java_lang_Class > pDrvClass = ::std::auto_ptr< java_lang_Class >(java_lang_Class::forName(aStr));
- if ( pDrvClass.get() )
- {
- m_pDriverobject = pDrvClass->newInstanceObject();
- if( t.pEnv && m_pDriverobject )
- m_pDriverobject = t.pEnv->NewGlobalRef( m_pDriverobject );
- if( t.pEnv )
- {
- jclass tempClass = t.pEnv->GetObjectClass(m_pDriverobject);
- if ( m_pDriverobject )
- {
- m_Driver_theClass = (jclass)t.pEnv->NewGlobalRef( tempClass );
- t.pEnv->DeleteLocalRef( tempClass );
- }
- }
- }
- }
+ pJavaDriverClass = pBegin;
+ }
+ else if (!pBegin->Name.compareToAscii("JavaDriverClassPath"))
+ {
+ pJavaDriverClassPath = pBegin;
}
else if(!pBegin->Name.compareToAscii("IsAutoRetrievingEnabled"))
{
@@ -742,6 +830,60 @@ void java_sql_Connection::loadDriverFromProperties(const Sequence< PropertyValue
OSL_VERIFY( pBegin->Value >>= _bIgnoreDriverPrivileges );
}
}
+ if ( !object && pJavaDriverClass != 0 )
+ {
+ // here I try to find the class for jdbc driver
+ java_sql_SQLException_BASE::getMyClass();
+ java_lang_Throwable::getMyClass();
+
+ ::rtl::OUString aStr;
+ OSL_VERIFY( pJavaDriverClass->Value >>= aStr );
+ OSL_ASSERT( aStr.getLength());
+ if ( aStr.getLength() )
+ {
+ // the driver manager holds the class of the driver for later use
+ ::std::auto_ptr< java_lang_Class > pDrvClass;
+ if ( pJavaDriverClassPath == 0 )
+ {
+ // if forName didn't find the class it will throw an exception
+ pDrvClass = ::std::auto_ptr< java_lang_Class >(java_lang_Class::forName(aStr));
+ }
+ else
+ {
+ ::rtl::OUString classpath;
+ OSL_VERIFY( pJavaDriverClassPath->Value >>= classpath );
+ pDrvClass.reset(
+ new java_lang_Class(
+ t.pEnv,
+ loadClass(
+ Reference< XComponentContext >(
+ Reference< XPropertySet >(
+ m_pDriver->getORB(),
+ UNO_QUERY_THROW)->getPropertyValue(
+ ::rtl::OUString(
+ RTL_CONSTASCII_USTRINGPARAM(
+ "DefaultContext"))),
+ UNO_QUERY_THROW),
+ t.pEnv, classpath, aStr)));
+ ThrowSQLException(t.pEnv, *this);
+ }
+ if ( pDrvClass.get() )
+ {
+ m_pDriverobject = pDrvClass->newInstanceObject();
+ if( t.pEnv && m_pDriverobject )
+ m_pDriverobject = t.pEnv->NewGlobalRef( m_pDriverobject );
+ if( t.pEnv )
+ {
+ jclass tempClass = t.pEnv->GetObjectClass(m_pDriverobject);
+ if ( m_pDriverobject )
+ {
+ m_Driver_theClass = (jclass)t.pEnv->NewGlobalRef( tempClass );
+ t.pEnv->DeleteLocalRef( tempClass );
+ }
+ }
+ }
+ }
+ }
}
catch(SQLException& e)
{