Tag: cws_src680_sb36
User: sb      
Date: 2007/03/05 08:52:57

Modified:
   dba/connectivity/source/drivers/jdbc/JConnection.cxx

Log:
 #i69624# Load each class only once.

File Changes:

Directory: /dba/connectivity/source/drivers/jdbc/
=================================================

File [changed]: JConnection.cxx
Url: 
http://dba.openoffice.org/source/browse/dba/connectivity/source/drivers/jdbc/JConnection.cxx?r1=1.2.28.2&r2=1.2.28.3
Delta lines:  +111 -4
---------------------
--- JConnection.cxx     22 Jan 2007 08:54:09 -0000      1.2.28.2
+++ JConnection.cxx     5 Mar 2007 16:52:53 -0000       1.2.28.3
@@ -4,9 +4,9 @@
  *
  *  $RCSfile: JConnection.cxx,v $
  *
- *  $Revision: 1.2.28.2 $
+ *  $Revision: 1.2.28.3 $
  *
- *  last change: $Author: sb $ $Date: 2007/01/22 08:54:09 $
+ *  last change: $Author: sb $ $Date: 2007/03/05 16:52:53 $
  *
  *  The Contents of this file are made available subject to
  *  the terms of GNU Lesser General Public License Version 2.1.
@@ -72,6 +72,10 @@
 #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;
@@ -82,6 +86,109 @@
 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");
 
//------------------------------------------------------------------------------
@@ -748,7 +855,7 @@
                     pDrvClass.reset(
                         new java_lang_Class(
                             t.pEnv,
-                            jvmaccess::ClassPath::loadClass(
+                            loadClass(
                                 Reference< XComponentContext >(
                                     Reference< XPropertySet >(
                                         m_pDriver->getORB(),




---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to