This is an automated email from the ASF dual-hosted git repository. rec pushed a commit to branch feature/107-Enable-loading-uimaFIT-annotators-and-other-classes-through-the-TCCL in repository https://gitbox.apache.org/repos/asf/uima-ruta.git
commit a1d259e45723b423fda8a242a5428eae5930d150 Author: Richard Eckart de Castilho <[email protected]> AuthorDate: Fri Sep 9 14:26:43 2022 +0200 Issue #107 - Enable loading uimaFIT annotators and other classes through the TCCL - consider the extensions classloader, TCCL and then the local classloader in that order --- .../org/apache/uima/ruta/engine/RutaEngine.java | 69 +++++++++++++++------- 1 file changed, 49 insertions(+), 20 deletions(-) diff --git a/ruta-core/src/main/java/org/apache/uima/ruta/engine/RutaEngine.java b/ruta-core/src/main/java/org/apache/uima/ruta/engine/RutaEngine.java index a4cc9016..9ea17fd2 100644 --- a/ruta-core/src/main/java/org/apache/uima/ruta/engine/RutaEngine.java +++ b/ruta-core/src/main/java/org/apache/uima/ruta/engine/RutaEngine.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,6 +19,9 @@ package org.apache.uima.ruta.engine; +import static java.util.Arrays.asList; +import static java.util.stream.Collectors.joining; + import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; @@ -521,7 +524,7 @@ public class RutaEngine extends JCasAnnotator_ImplBase { * This parameter specifies annotation types (resolvable mentions are also supported) that should * be indexed additionally to types mentioned in the rules. This parameter is only used if the * parameter 'indexOnlyMentionedTypes' is activated. - * + * */ public static final String PARAM_INDEX_ADDITONALLY = "indexAdditionally"; @@ -542,7 +545,7 @@ public class RutaEngine extends JCasAnnotator_ImplBase { * This parameter specifies the mode for updating the internal indexing in RutaBasic annotations. * This is a technical parameter for optimizing the runtime performance/speed of RutaEngines. * Available modes are: COMPLETE, ADDITIVE, SAFE_ADDITIVE, NONE. Default value is ADDITIVE. - * + * */ public static final String PARAM_REINDEX_UPDATE_MODE = "reindexUpdateMode"; @@ -582,7 +585,7 @@ public class RutaEngine extends JCasAnnotator_ImplBase { * This parameter specifies optional class names implementing the interface * <code>org.apache.uima.ruta.visitor.RutaInferenceVisitor</code>, which will be notified during * applying the rules. - * + * */ public static final String PARAM_INFERENCE_VISITORS = "inferenceVisitors"; @@ -836,7 +839,7 @@ public class RutaEngine extends JCasAnnotator_ImplBase { } for (String each : additionalExtensions) { try { - Class<?> forName = getClassLoader().loadClass(each); + Class<?> forName = loadClass(each); if (IRutaExtension.class.isAssignableFrom(forName)) { IRutaExtension extension = (IRutaExtension) forName.newInstance(); verbalizer.addExternalVerbalizers(extension); @@ -850,15 +853,6 @@ public class RutaEngine extends JCasAnnotator_ImplBase { } } - private ClassLoader getClassLoader() { - ClassLoader extensionClassLoader = resourceManager.getExtensionClassLoader(); - if (extensionClassLoader == null) { - return this.getClass().getClassLoader(); - } - return extensionClassLoader; - - } - private InferenceCrowd initializeCrowd() { List<RutaInferenceVisitor> visitors = new ArrayList<RutaInferenceVisitor>(); if (debug) { @@ -877,7 +871,7 @@ public class RutaEngine extends JCasAnnotator_ImplBase { if (inferenceVisitors != null && inferenceVisitors.length != 0) { for (String eachClassName : inferenceVisitors) { try { - Class<?> forName = getClassLoader().loadClass(eachClassName); + Class<?> forName = loadClass(eachClassName); if (RutaInferenceVisitor.class.isAssignableFrom(forName)) { RutaInferenceVisitor visitor = (RutaInferenceVisitor) forName.newInstance(); visitors.add(visitor); @@ -930,7 +924,7 @@ public class RutaEngine extends JCasAnnotator_ImplBase { for (String seederClass : seeders) { Class<?> loadClass = null; try { - loadClass = getClassLoader().loadClass(seederClass); + loadClass = loadClass(seederClass); } catch (ClassNotFoundException e) { throw new AnalysisEngineProcessException(e); } @@ -1099,9 +1093,7 @@ public class RutaEngine extends JCasAnnotator_ImplBase { throws AnalysisEngineProcessException { AnalysisEngine eachEngine = null; try { - @SuppressWarnings("unchecked") - Class<? extends AnalysisComponent> uimafitClass = (Class<? extends AnalysisComponent>) getClassLoader() - .loadClass(eachUimafitEngine); + Class<? extends AnalysisComponent> uimafitClass = loadClass(eachUimafitEngine); List<String> configurationData = script.getConfigurationData(eachUimafitEngine); AnalysisEngineDescription aed = AnalysisEngineFactory.createEngineDescription(uimafitClass, configurationData.toArray()); @@ -1112,6 +1104,43 @@ public class RutaEngine extends JCasAnnotator_ImplBase { addAnalysisEngineToMap(additionalEnginesMap, eachUimafitEngine, eachEngine); } + @SuppressWarnings("unchecked") + private static <T> Class<T> loadClass(String className, ClassLoader... classLoaders) + throws ClassNotFoundException { + List<String> errors = new ArrayList<>(); + List<ClassLoader> classLoadersTried = new ArrayList<>(); + for (ClassLoader cl : classLoaders) { + if (cl == null) { + continue; + } + + classLoadersTried.add(cl); + try { + return (Class<T>) cl.loadClass(className); + } catch (ClassNotFoundException e) { + errors.add(e.getMessage()); + // Class not found in the resource manager's extension classloader - try next + } + } + + String classLoaderList = asList(classLoadersTried).stream() // + .map(Object::toString) // + .collect(joining(", ")); + String errorList = errors.stream().collect(joining("\n- ", "\n- ", "")); + + throw new ClassNotFoundException(className + " cannot be found by any of the classloaders [" + + classLoaderList + "]: " + errorList); + } + + private <T> Class<T> loadClass(String className) + throws ClassNotFoundException { + ClassLoader extCl = resourceManager.getExtensionClassLoader(); + ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + ClassLoader local = getClass().getClassLoader(); + + return loadClass(className, extCl, tccl, local); + } + private String getModuleName(String completeNamespace) { int lastIndexOf = completeNamespace.lastIndexOf('.'); if (lastIndexOf != -1) {
