You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@uima.apache.org by re...@apache.org on 2020/10/15 11:51:11 UTC
[uima-uimafit] branch
bugfix/UIMA-6275-InitializableFactory-is-not-smart-enough-to-find-a-suitable-classloader
created (now ee1c697)
This is an automated email from the ASF dual-hosted git repository.
rec pushed a change to branch bugfix/UIMA-6275-InitializableFactory-is-not-smart-enough-to-find-a-suitable-classloader
in repository https://gitbox.apache.org/repos/asf/uima-uimafit.git.
at ee1c697 [UIMA-6275] InitializableFactory is not smart enough to find a suitable classloader
This branch includes the following new commits:
new ee1c697 [UIMA-6275] InitializableFactory is not smart enough to find a suitable classloader
The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails. The revisions
listed as "add" were already present in the repository and have only
been added to this reference.
[uima-uimafit] 01/01: [UIMA-6275] InitializableFactory is not smart
enough to find a suitable classloader
Posted by re...@apache.org.
This is an automated email from the ASF dual-hosted git repository.
rec pushed a commit to branch bugfix/UIMA-6275-InitializableFactory-is-not-smart-enough-to-find-a-suitable-classloader
in repository https://gitbox.apache.org/repos/asf/uima-uimafit.git
commit ee1c69709755032c61c4ca7688195f5d259e97eb
Author: Richard Eckart de Castilho <re...@apache.org>
AuthorDate: Thu Oct 15 13:50:26 2020 +0200
[UIMA-6275] InitializableFactory is not smart enough to find a suitable classloader
- Introduce a new uimaFIT-specifc internal utility class for classloader lookups
- Use the methods provided by this class in the InitializableFactory
- Also use it in other places where we need to find a suitable classloader
---
.../apache/uima/fit/factory/FsIndexFactory.java | 8 +-
.../uima/fit/factory/TypePrioritiesFactory.java | 8 +-
.../fit/factory/TypeSystemDescriptionFactory.java | 10 +-
.../initializable/InitializableFactory.java | 21 +++-
.../apache/uima/fit/internal/ClassloaderUtils.java | 123 +++++++++++++++++++++
.../uima/fit/internal/ResourceManagerFactory.java | 77 +++++++------
6 files changed, 188 insertions(+), 59 deletions(-)
diff --git a/uimafit-core/src/main/java/org/apache/uima/fit/factory/FsIndexFactory.java b/uimafit-core/src/main/java/org/apache/uima/fit/factory/FsIndexFactory.java
index bfc7923..a210ef7 100644
--- a/uimafit-core/src/main/java/org/apache/uima/fit/factory/FsIndexFactory.java
+++ b/uimafit-core/src/main/java/org/apache/uima/fit/factory/FsIndexFactory.java
@@ -31,6 +31,7 @@ import java.util.WeakHashMap;
import org.apache.commons.logging.LogFactory;
import org.apache.uima.fit.descriptor.FsIndex;
import org.apache.uima.fit.descriptor.FsIndexKey;
+import org.apache.uima.fit.internal.ClassloaderUtils;
import org.apache.uima.fit.internal.MetaDataType;
import org.apache.uima.resource.ResourceInitializationException;
import org.apache.uima.resource.metadata.FsIndexCollection;
@@ -43,7 +44,6 @@ import org.apache.uima.resource.metadata.impl.FsIndexKeyDescription_impl;
import org.apache.uima.resource.metadata.impl.Import_impl;
import org.apache.uima.util.InvalidXMLException;
import org.apache.uima.util.XMLInputSource;
-import org.springframework.util.ClassUtils;
/**
*/
@@ -259,7 +259,7 @@ public final class FsIndexFactory {
* if the index collection could not be assembled
*/
public static FsIndexCollection createFsIndexCollection() throws ResourceInitializationException {
- ClassLoader cl = ClassUtils.getDefaultClassLoader();
+ ClassLoader cl = ClassloaderUtils.findClassloader();
FsIndexCollection aggFsIdxCol = fsIndexCollectionsByClassloader.get(cl);
if (aggFsIdxCol == null) {
synchronized (CREATE_LOCK) {
@@ -275,7 +275,7 @@ public final class FsIndexFactory {
throw new ResourceInitializationException(e);
} catch (InvalidXMLException e) {
LogFactory.getLog(FsIndexFactory.class)
- .warn("[" + location + "] is not a index descriptor file. Ignoring.", e);
+ .warn("[" + location + "] is not a index descriptor file. Ignoring.", e);
}
}
@@ -299,7 +299,7 @@ public final class FsIndexFactory {
*/
public static String[] scanIndexDescriptors() throws ResourceInitializationException {
synchronized (SCAN_LOCK) {
- ClassLoader cl = ClassUtils.getDefaultClassLoader();
+ ClassLoader cl = ClassloaderUtils.findClassloader();
String[] indexLocations = fsIndexLocationsByClassloader.get(cl);
if (indexLocations == null) {
indexLocations = scanDescriptors(MetaDataType.FS_INDEX);
diff --git a/uimafit-core/src/main/java/org/apache/uima/fit/factory/TypePrioritiesFactory.java b/uimafit-core/src/main/java/org/apache/uima/fit/factory/TypePrioritiesFactory.java
index 1759bc9..c79abaa 100644
--- a/uimafit-core/src/main/java/org/apache/uima/fit/factory/TypePrioritiesFactory.java
+++ b/uimafit-core/src/main/java/org/apache/uima/fit/factory/TypePrioritiesFactory.java
@@ -28,6 +28,7 @@ import java.util.List;
import java.util.WeakHashMap;
import org.apache.commons.logging.LogFactory;
+import org.apache.uima.fit.internal.ClassloaderUtils;
import org.apache.uima.fit.internal.MetaDataType;
import org.apache.uima.fit.internal.ResourceManagerFactory;
import org.apache.uima.resource.ResourceInitializationException;
@@ -38,7 +39,6 @@ import org.apache.uima.resource.metadata.impl.TypePriorities_impl;
import org.apache.uima.util.CasCreationUtils;
import org.apache.uima.util.InvalidXMLException;
import org.apache.uima.util.XMLInputSource;
-import org.springframework.util.ClassUtils;
public final class TypePrioritiesFactory {
private static final Object SCAN_LOCK = new Object();
@@ -105,7 +105,7 @@ public final class TypePrioritiesFactory {
* if the collected type priorities cannot be merged.
*/
public static TypePriorities createTypePriorities() throws ResourceInitializationException {
- ClassLoader cl = ClassUtils.getDefaultClassLoader();
+ ClassLoader cl = ClassloaderUtils.findClassloader();
TypePriorities aggTypePriorities = typePrioritiesByClassloader.get(cl);
if (aggTypePriorities == null) {
synchronized (CREATE_LOCK) {
@@ -117,7 +117,7 @@ public final class TypePrioritiesFactory {
typePriorities.resolveImports();
typePrioritiesList.add(typePriorities);
LogFactory.getLog(TypePrioritiesFactory.class)
- .debug("Detected type priorities at [" + location + "]");
+ .debug("Detected type priorities at [" + location + "]");
} catch (IOException e) {
throw new ResourceInitializationException(e);
} catch (InvalidXMLException e) {
@@ -146,7 +146,7 @@ public final class TypePrioritiesFactory {
*/
public static String[] scanTypePrioritiesDescriptors() throws ResourceInitializationException {
synchronized (SCAN_LOCK) {
- ClassLoader cl = ClassUtils.getDefaultClassLoader();
+ ClassLoader cl = ClassloaderUtils.findClassloader();
String[] typePrioritesLocations = typePrioritesLocationsByClassloader.get(cl);
if (typePrioritesLocations == null) {
typePrioritesLocations = scanDescriptors(MetaDataType.TYPE_PRIORITIES);
diff --git a/uimafit-core/src/main/java/org/apache/uima/fit/factory/TypeSystemDescriptionFactory.java b/uimafit-core/src/main/java/org/apache/uima/fit/factory/TypeSystemDescriptionFactory.java
index ab3e9f8..dd2a246 100644
--- a/uimafit-core/src/main/java/org/apache/uima/fit/factory/TypeSystemDescriptionFactory.java
+++ b/uimafit-core/src/main/java/org/apache/uima/fit/factory/TypeSystemDescriptionFactory.java
@@ -28,6 +28,7 @@ import java.util.List;
import java.util.WeakHashMap;
import org.apache.commons.logging.LogFactory;
+import org.apache.uima.fit.internal.ClassloaderUtils;
import org.apache.uima.fit.internal.MetaDataType;
import org.apache.uima.fit.internal.ResourceManagerFactory;
import org.apache.uima.resource.ResourceInitializationException;
@@ -38,7 +39,6 @@ import org.apache.uima.resource.metadata.impl.Import_impl;
import org.apache.uima.resource.metadata.impl.TypeSystemDescription_impl;
import org.apache.uima.util.InvalidXMLException;
import org.apache.uima.util.XMLInputSource;
-import org.springframework.util.ClassUtils;
public final class TypeSystemDescriptionFactory {
private static final Object SCAN_LOCK = new Object();
@@ -110,7 +110,7 @@ public final class TypeSystemDescriptionFactory {
*/
public static TypeSystemDescription createTypeSystemDescription()
throws ResourceInitializationException {
- ClassLoader cl = ClassUtils.getDefaultClassLoader();
+ ClassLoader cl = ClassloaderUtils.findClassloader();
TypeSystemDescription tsd = typeDescriptorByClassloader.get(cl);
if (tsd == null) {
synchronized (CREATE_LOCK) {
@@ -120,12 +120,12 @@ public final class TypeSystemDescriptionFactory {
XMLInputSource xmlInputType1 = new XMLInputSource(location);
tsdList.add(getXMLParser().parseTypeSystemDescription(xmlInputType1));
LogFactory.getLog(TypeSystemDescription.class)
- .debug("Detected type system at [" + location + "]");
+ .debug("Detected type system at [" + location + "]");
} catch (IOException e) {
throw new ResourceInitializationException(e);
} catch (InvalidXMLException e) {
LogFactory.getLog(TypeSystemDescription.class)
- .warn("[" + location + "] is not a type file. Ignoring.", e);
+ .warn("[" + location + "] is not a type file. Ignoring.", e);
}
}
@@ -148,7 +148,7 @@ public final class TypeSystemDescriptionFactory {
*/
public static String[] scanTypeDescriptors() throws ResourceInitializationException {
synchronized (SCAN_LOCK) {
- ClassLoader cl = ClassUtils.getDefaultClassLoader();
+ ClassLoader cl = ClassloaderUtils.findClassloader();
String[] typeDescriptorLocations = typeDescriptorLocationsByClassloader.get(cl);
if (typeDescriptorLocations == null) {
typeDescriptorLocations = scanDescriptors(MetaDataType.TYPE_SYSTEM);
diff --git a/uimafit-core/src/main/java/org/apache/uima/fit/factory/initializable/InitializableFactory.java b/uimafit-core/src/main/java/org/apache/uima/fit/factory/initializable/InitializableFactory.java
index e0c54e6..906538a 100644
--- a/uimafit-core/src/main/java/org/apache/uima/fit/factory/initializable/InitializableFactory.java
+++ b/uimafit-core/src/main/java/org/apache/uima/fit/factory/initializable/InitializableFactory.java
@@ -6,9 +6,9 @@
* 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
@@ -19,11 +19,12 @@
package org.apache.uima.fit.factory.initializable;
import org.apache.uima.UimaContext;
+import org.apache.uima.fit.internal.ClassloaderUtils;
import org.apache.uima.resource.ResourceInitializationException;
/**
* Please see {@link Initializable} for a description of how this class is intended to be used.
- *
+ *
* @see Initializable
*/
public final class InitializableFactory {
@@ -35,7 +36,7 @@ public final class InitializableFactory {
* Provides a way to create an instance of T. If the class specified by className implements
* {@link Initializable}, then the UimaContext provided here will be passed to its initialize
* method.
- *
+ *
* @param <T>
* the interface type
* @param context
@@ -50,7 +51,14 @@ public final class InitializableFactory {
*/
public static <T> T create(UimaContext context, String className, Class<T> superClass)
throws ResourceInitializationException {
- Class<? extends T> cls = getClass(className, superClass);
+ Class<? extends T> cls;
+ try {
+ ClassLoader cl = ClassloaderUtils.findClassloader(context);
+ cls = Class.forName(className, true, cl).asSubclass(superClass);
+ } catch (Exception e) {
+ throw new ResourceInitializationException(new IllegalStateException("classname = "
+ + className + " superClass = " + superClass.getName(), e));
+ }
return create(context, cls);
}
@@ -68,7 +76,8 @@ public final class InitializableFactory {
public static <T> Class<? extends T> getClass(String className, Class<T> superClass)
throws ResourceInitializationException {
try {
- return Class.forName(className).asSubclass(superClass);
+ ClassLoader cl = ClassloaderUtils.findClassloader();
+ return Class.forName(className, true, cl).asSubclass(superClass);
} catch (Exception e) {
throw new ResourceInitializationException(new IllegalStateException("classname = "
+ className + " superClass = " + superClass.getName(), e));
diff --git a/uimafit-core/src/main/java/org/apache/uima/fit/internal/ClassloaderUtils.java b/uimafit-core/src/main/java/org/apache/uima/fit/internal/ClassloaderUtils.java
new file mode 100644
index 0000000..2dc3671
--- /dev/null
+++ b/uimafit-core/src/main/java/org/apache/uima/fit/internal/ClassloaderUtils.java
@@ -0,0 +1,123 @@
+/*
+ * 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 org.apache.uima.fit.internal;
+
+import org.apache.uima.UimaContext;
+import org.apache.uima.UimaContextAdmin;
+import org.apache.uima.UimaContextHolder;
+import org.apache.uima.resource.ResourceManager;
+import org.springframework.util.ClassUtils;
+
+/**
+ * INTERNAL API - Helper functions to obtain a suitable classloader.
+ */
+public final class ClassloaderUtils {
+ private ClassloaderUtils() {
+ // No instances
+ }
+
+ /**
+ * Looks up a suitable classloader in the following order:
+ * <ol>
+ * <li>The {@link UimaContext} in the {@link UimaContextHolder} of the current thread(if any)</li>
+ * <li>The current thread-context classloader (if any)</li>
+ * <li>The classloader through which uimaFIT (i.e. this class) was loaded.</li>
+ * <li>For backwards compatibility then delegates to {@link ClassUtils#getDefaultClassLoader()}</li>
+ * </ol>
+ *
+ * @return a classloader or {@code null} if no suitable classloader could be found.
+ */
+ public static ClassLoader findClassloader() {
+ ClassLoader uimaThreadContextClassLoader = getExtensionClassloader(
+ UimaContextHolder.getContext());
+ if (uimaThreadContextClassLoader != null) {
+ return uimaThreadContextClassLoader;
+ }
+
+ ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
+ if (contextClassLoader != null) {
+ return contextClassLoader;
+ }
+
+ ClassLoader uimaFITClassLoader = ClassloaderUtils.class.getClassLoader();
+ if (uimaFITClassLoader != null) {
+ return uimaFITClassLoader;
+ }
+
+ return ClassUtils.getDefaultClassLoader();
+ }
+
+ /**
+ * Looks up a suitable classloader in the following order:
+ * <ol>
+ * <li>The extension classloader of the given {@link ResourceManager}</li>
+ * <li>{@see #findClassloader()}</li>
+ * </ol>
+ *
+ * @return a classloader or {@code null} if no suitable classloader could be found.
+ */
+ public static ClassLoader findClassloader(ResourceManager aResMgr) {
+ ClassLoader resourceManagerExtensionClassloader = getExtensionClassloader(aResMgr);
+ if (resourceManagerExtensionClassloader != null) {
+ return resourceManagerExtensionClassloader;
+ }
+
+ return findClassloader();
+ }
+
+ /**
+ * Looks up a suitable classloader in the following order:
+ * <ol>
+ * <li>The extension classloader of the {@link ResourceManager} associated with the given
+ * {@link UimaContext} (if any)</li>
+ * <li>{@see #findClassloader(ResourceManager)}</li>
+ * </ol>
+ *
+ * @return a classloader or {@code null} if no suitable classloader could be found.
+ */
+ public static ClassLoader findClassloader(UimaContext aContext) {
+ ClassLoader uimaContextExtensionClassloader = getExtensionClassloader(aContext);
+ if (uimaContextExtensionClassloader != null) {
+ return uimaContextExtensionClassloader;
+ }
+
+ return findClassloader((ResourceManager) null);
+ }
+
+ private static ClassLoader getExtensionClassloader(UimaContext aContext) {
+ if (aContext instanceof UimaContextAdmin) {
+ return getExtensionClassloader(((UimaContextAdmin) aContext).getResourceManager());
+ }
+
+ return null;
+ }
+
+ private static ClassLoader getExtensionClassloader(ResourceManager aResMgr) {
+ if (aResMgr == null) {
+ return null;
+ }
+
+ ClassLoader cl = aResMgr.getExtensionClassLoader();
+ if (cl != null) {
+ return aResMgr.getExtensionClassLoader();
+ }
+
+ return null;
+ }
+}
diff --git a/uimafit-core/src/main/java/org/apache/uima/fit/internal/ResourceManagerFactory.java b/uimafit-core/src/main/java/org/apache/uima/fit/internal/ResourceManagerFactory.java
index 5bf34fa..e3e40b1 100644
--- a/uimafit-core/src/main/java/org/apache/uima/fit/internal/ResourceManagerFactory.java
+++ b/uimafit-core/src/main/java/org/apache/uima/fit/internal/ResourceManagerFactory.java
@@ -6,9 +6,9 @@
* 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
@@ -28,16 +28,15 @@ import org.apache.uima.impl.UimaVersion;
import org.apache.uima.resource.ResourceInitializationException;
import org.apache.uima.resource.ResourceManager;
import org.apache.uima.resource.impl.ResourceManager_impl;
-import org.springframework.util.ClassUtils;
/**
* INTERNAL API - Helper functions for dealing with resource managers and classloading
- *
- * This API is experimental and is very likely to be removed or changed in future versions.
+ *
+ * This API is experimental and is very likely to be removed or changed in future versions.
*/
public class ResourceManagerFactory {
private static ResourceManagerCreator resourceManagerCreator = new DefaultResourceManagerCreator();
-
+
private ResourceManagerFactory() {
// No instances
}
@@ -46,7 +45,7 @@ public class ResourceManagerFactory {
{
return resourceManagerCreator.newResourceManager();
}
-
+
/**
* Mind that returning a singleton resource manager from {@link ResourceManagerFactory} is
* generally a bad idea because it gets destroyed on a regular basis. For this reason, it is
@@ -57,15 +56,15 @@ public class ResourceManagerFactory {
ResourceManagerCreator resourceManagerCreator) {
ResourceManagerFactory.resourceManagerCreator = resourceManagerCreator;
}
-
+
public static ResourceManagerCreator getResourceManagerCreator() {
return resourceManagerCreator;
}
-
- public static interface ResourceManagerCreator {
+
+ public interface ResourceManagerCreator {
ResourceManager newResourceManager() throws ResourceInitializationException;
}
-
+
public static class DefaultResourceManagerCreator implements ResourceManagerCreator {
@Override
public ResourceManager newResourceManager() throws ResourceInitializationException {
@@ -78,37 +77,35 @@ public class ResourceManagerFactory {
// See https://issues.apache.org/jira/browse/UIMA-5056
return ((UimaContextAdmin) activeContext).getResourceManager();
}
+
+ // If there is no UIMA context, then we create a new resource manager
+ // UIMA core still does not fall back to the context classloader in all cases.
+ // This was the default behavior until uimaFIT 2.2.0.
+ ResourceManager resMgr;
+ if (Thread.currentThread().getContextClassLoader() != null) {
+ // If the context classloader is set, then we want the resource manager to fallb
+ // back to it. However, it may not reliably do that that unless we explictly pass
+ // null here. See. UIMA-6239.
+ resMgr = new ResourceManager_impl(null);
+ }
else {
- // If there is no UIMA context, then we create a new resource manager
- // UIMA core still does not fall back to the context classloader in all cases.
- // This was the default behavior until uimaFIT 2.2.0.
- ResourceManager resMgr;
- if (Thread.currentThread().getContextClassLoader() != null) {
- // If the context classloader is set, then we want the resource manager to fallb
- // back to it. However, it may not reliably do that that unless we explictly pass
- // null here. See. UIMA-6239.
- resMgr = new ResourceManager_impl(null);
- }
- else {
- resMgr = UIMAFramework.newDefaultResourceManager();
- }
-
-
- // Since UIMA Core version 2.10.3 and 3.0.1 the thread context classloader is taken
- // into account by the core framework. Thus, we no longer have to explicitly set a
- // classloader these or more recent versions. (cf. UIMA-5802)
- short maj = UimaVersion.getMajorVersion();
- short min = UimaVersion.getMinorVersion();
- short rev = UimaVersion.getBuildRevision();
- boolean uimaCoreIgnoresContextClassloader =
- (maj == 2 && (min < 10 || (min == 10 && rev < 3))) || // version < 2.10.3
- (maj == 3 && ((min == 0 && rev < 1))); // version < 3.0.1
- if (uimaCoreIgnoresContextClassloader) {
- resMgr.setExtensionClassPath(ClassUtils.getDefaultClassLoader(), "", true);
- }
-
- return resMgr;
+ resMgr = UIMAFramework.newDefaultResourceManager();
}
+
+ // Since UIMA Core version 2.10.3 and 3.0.1 the thread context classloader is taken
+ // into account by the core framework. Thus, we no longer have to explicitly set a
+ // classloader these or more recent versions. (cf. UIMA-5802)
+ short maj = UimaVersion.getMajorVersion();
+ short min = UimaVersion.getMinorVersion();
+ short rev = UimaVersion.getBuildRevision();
+ boolean uimaCoreIgnoresContextClassloader =
+ (maj == 2 && (min < 10 || (min == 10 && rev < 3))) || // version < 2.10.3
+ (maj == 3 && ((min == 0 && rev < 1))); // version < 3.0.1
+ if (uimaCoreIgnoresContextClassloader) {
+ resMgr.setExtensionClassPath(ClassloaderUtils.findClassloader(), "", true);
+ }
+
+ return resMgr;
}
catch (MalformedURLException e) {
throw new ResourceInitializationException(e);