[Libreoffice-commits] core.git: Branch 'aoo/trunk' - connectivity/java
Libreoffice Gerrit user
logerrit at kemper.freedesktop.org
Mon Dec 3 17:08:11 UTC 2018
connectivity/java/sdbc_jdbc/src/com/sun/star/comp/sdbc/JavaSQLConnection.java | 3
connectivity/java/sdbc_jdbc/src/com/sun/star/comp/sdbc/classloading/ClassLoaderAndClass.java | 46 +++
connectivity/java/sdbc_jdbc/src/com/sun/star/comp/sdbc/classloading/ClassMap.java | 150 ++++++++++
3 files changed, 198 insertions(+), 1 deletion(-)
New commits:
commit 40424188a15d5253b23ff5a7f96a472ffa899534
Author: Damjan Jovanovic <damjan at apache.org>
AuthorDate: Mon Dec 3 17:03:12 2018 +0000
Commit: Damjan Jovanovic <damjan at apache.org>
CommitDate: Mon Dec 3 17:03:12 2018 +0000
Refactor classloading in the postgresql driver.
Patch by: me
diff --git a/connectivity/java/sdbc_jdbc/src/com/sun/star/comp/sdbc/JavaSQLConnection.java b/connectivity/java/sdbc_jdbc/src/com/sun/star/comp/sdbc/JavaSQLConnection.java
index f4fb4298ae6f..7535cb6f67b1 100644
--- a/connectivity/java/sdbc_jdbc/src/com/sun/star/comp/sdbc/JavaSQLConnection.java
+++ b/connectivity/java/sdbc_jdbc/src/com/sun/star/comp/sdbc/JavaSQLConnection.java
@@ -20,6 +20,7 @@
*************************************************************/
package com.sun.star.comp.sdbc;
+import com.sun.star.comp.sdbc.classloading.ClassMap;
import java.util.Iterator;
import java.util.Properties;
@@ -31,7 +32,7 @@ import org.apache.openoffice.comp.sdbc.dbtools.util.StandardSQLState;
import com.sun.star.beans.NamedValue;
import com.sun.star.beans.PropertyValue;
-import com.sun.star.comp.sdbc.ClassMap.ClassLoaderAndClass;
+import com.sun.star.comp.sdbc.classloading.ClassLoaderAndClass;
import com.sun.star.comp.sdbc.ConnectionLog.ObjectType;
import com.sun.star.container.XNameAccess;
import com.sun.star.lang.IllegalArgumentException;
diff --git a/connectivity/java/sdbc_jdbc/src/com/sun/star/comp/sdbc/classloading/ClassLoaderAndClass.java b/connectivity/java/sdbc_jdbc/src/com/sun/star/comp/sdbc/classloading/ClassLoaderAndClass.java
new file mode 100644
index 000000000000..c3946c8c5bd9
--- /dev/null
+++ b/connectivity/java/sdbc_jdbc/src/com/sun/star/comp/sdbc/classloading/ClassLoaderAndClass.java
@@ -0,0 +1,46 @@
+/**************************************************************
+ *
+ * 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
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *************************************************************/
+
+package com.sun.star.comp.sdbc.classloading;
+
+/**
+ *
+ * @author dacha
+ */
+public class ClassLoaderAndClass {
+
+ private final ClassLoader classLoader;
+ private final Class<?> classObject;
+
+ public ClassLoaderAndClass(ClassLoader classLoader, Class<?> classObject) {
+ this.classLoader = classLoader;
+ this.classObject = classObject;
+ }
+
+ public ClassLoader getClassLoader() {
+ return classLoader;
+ }
+
+ public Class<?> getClassObject() {
+ return classObject;
+ }
+
+}
diff --git a/connectivity/java/sdbc_jdbc/src/com/sun/star/comp/sdbc/classloading/ClassMap.java b/connectivity/java/sdbc_jdbc/src/com/sun/star/comp/sdbc/classloading/ClassMap.java
new file mode 100644
index 000000000000..b8a03af52858
--- /dev/null
+++ b/connectivity/java/sdbc_jdbc/src/com/sun/star/comp/sdbc/classloading/ClassMap.java
@@ -0,0 +1,150 @@
+/**************************************************************
+ *
+ * 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
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ *************************************************************/
+package com.sun.star.comp.sdbc.classloading;
+
+import java.lang.ref.WeakReference;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.apache.openoffice.comp.sdbc.dbtools.comphelper.CompHelper;
+
+import com.sun.star.lang.IllegalArgumentException;
+import com.sun.star.uno.RuntimeException;
+import com.sun.star.uno.UnoRuntime;
+import com.sun.star.uno.XComponentContext;
+import com.sun.star.uri.UriReferenceFactory;
+import com.sun.star.uri.XUriReferenceFactory;
+import com.sun.star.uri.XVndSunStarExpandUrlReference;
+import com.sun.star.util.XMacroExpander;
+
+/**
+ * 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.
+ */
+public class ClassMap {
+
+ private static class ClassMapEntry {
+ String classPath;
+ String className;
+ WeakReference<ClassLoader> classLoader;
+ WeakReference<Class<?>> classObject;
+ }
+
+ private final LinkedList<ClassMapEntry> map = new LinkedList<>();
+
+ public synchronized ClassLoaderAndClass loadClass(XComponentContext context, String classPath, String className)
+ throws MalformedURLException, ClassNotFoundException {
+
+ ClassLoader classLoader = null;
+ Class<?> classObject = null;
+ // Prune dangling weak references from the list while searching for a match,
+ // so that the list cannot grow unbounded:
+ ClassMapEntry matchingEntry = null;
+ for (Iterator<ClassMapEntry> it = map.iterator(); it.hasNext();) {
+ ClassMapEntry entry = it.next();
+ classLoader = entry.classLoader.get();
+ classObject = entry.classObject.get();
+ if (classLoader == null && classObject == null) {
+ it.remove();
+ } else if (entry.classPath.equals(classPath) && entry.className.equals(className)) {
+ matchingEntry = entry;
+ break;
+ }
+ }
+ if (classLoader == null || classObject == null) {
+ if (matchingEntry == 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 (return false, etc.) it will be pruned on next
+ // call because its classLoader/classObject are null:
+ matchingEntry = new ClassMapEntry();
+ matchingEntry.classPath = classPath;
+ matchingEntry.className = className;
+ map.addFirst(matchingEntry);
+ }
+ if (classLoader == null) {
+ List<URL> urls = translateToUrls(context, classPath);
+ classLoader = new URLClassLoader(urls.toArray(new URL[0]));
+ }
+ if (classObject == null) {
+ classObject = classLoader.loadClass(className);
+ }
+ matchingEntry.classLoader = new WeakReference<ClassLoader>(classLoader);
+ matchingEntry.classObject = new WeakReference<Class<?>>(classObject);
+ }
+ return new ClassLoaderAndClass(classLoader, classObject);
+ }
+
+ private static List<URL> translateToUrls(XComponentContext context, String classPath) throws MalformedURLException {
+ StringTokenizer tokenizer = new StringTokenizer(classPath, " ", false);
+ ArrayList<URL> urls = new ArrayList<>();
+ while (tokenizer.hasMoreTokens()) {
+ String url = tokenizer.nextToken();
+ XUriReferenceFactory uriReferenceFactory = null;
+ XVndSunStarExpandUrlReference expUrl = null;
+ XMacroExpander macroExpander = null;
+ try {
+ uriReferenceFactory = UriReferenceFactory.create(context);
+ expUrl = UnoRuntime.queryInterface(
+ XVndSunStarExpandUrlReference.class, uriReferenceFactory.parse(url));
+ if (expUrl != null) {
+ macroExpander = UnoRuntime.queryInterface(
+ XMacroExpander.class,
+ context.getValueByName("/singletons/com.sun.star.util.theMacroExpander"));
+ try {
+ url = expUrl.expand(macroExpander);
+ } catch (IllegalArgumentException illegalArgumentException) {
+ throw new RuntimeException(
+ "com.sun.star.lang.IllegalArgumentException: " + illegalArgumentException.getMessage(),
+ illegalArgumentException);
+ }
+ }
+ } finally {
+ CompHelper.disposeComponent(uriReferenceFactory);
+ CompHelper.disposeComponent(expUrl);
+ CompHelper.disposeComponent(macroExpander);
+ }
+ URL javaURL = new URL(url);
+ urls.add(javaURL);
+ }
+ return urls;
+ }
+}
More information about the Libreoffice-commits
mailing list