You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by re...@apache.org on 2022/08/13 22:32:21 UTC

[cxf] 01/02: CXF-8732: [regression] activation DataSource requires to run JAXRS

This is an automated email from the ASF dual-hosted git repository.

reta pushed a commit to branch 3.5.x-fixes
in repository https://gitbox.apache.org/repos/asf/cxf.git

commit 41a7c8b358aab1ad219a4b7924411cbcfc9edd06
Author: Andriy Redko <dr...@gmail.com>
AuthorDate: Sat Aug 13 18:28:29 2022 -0400

    CXF-8732: [regression] activation DataSource requires to run JAXRS
---
 .../org/apache/cxf/jaxrs/utils/JAXRSUtils.java     | 39 ++++++++++++++++++++--
 1 file changed, 37 insertions(+), 2 deletions(-)

diff --git a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
index 15d00fe51e..a97938fc19 100644
--- a/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
+++ b/rt/frontend/jaxrs/src/main/java/org/apache/cxf/jaxrs/utils/JAXRSUtils.java
@@ -39,6 +39,7 @@ import java.util.LinkedHashMap;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map;
+import java.util.Optional;
 import java.util.ResourceBundle;
 import java.util.Set;
 import java.util.SortedMap;
@@ -48,7 +49,6 @@ import java.util.logging.Level;
 import java.util.logging.Logger;
 import java.util.stream.Collectors;
 
-import javax.activation.DataSource;
 import javax.ws.rs.ClientErrorException;
 import javax.ws.rs.Consumes;
 import javax.ws.rs.HttpMethod;
@@ -85,6 +85,7 @@ import javax.ws.rs.ext.WriterInterceptorContext;
 import javax.xml.namespace.QName;
 import javax.xml.transform.Source;
 
+import org.apache.cxf.common.classloader.ClassLoaderUtils;
 import org.apache.cxf.common.i18n.BundleUtils;
 import org.apache.cxf.common.logging.LogUtils;
 import org.apache.cxf.common.util.PackageUtils;
@@ -202,6 +203,40 @@ public final class JAXRSUtils {
             "java.util.concurrent.CompletableFuture",
             "java.util.concurrent.CompletionStage"
         ));
+    private static final LazyLoadedClass DATA_SOURCE_CLASS = new LazyLoadedClass("javax.activation.DataSource");
+
+    // Class to lazily call the ClassLoaderUtil.loadClass, but do it once
+    // and cache the result.  Then use the class to create instances as needed.
+    // This avoids calling loadClass every time as calling loadClass is super expensive, 
+    // particularly if the class cannot be found and particularly in OSGi where the 
+    // search is very complex. This would record that the class is not found and prevent 
+    // future searches.
+    private static class LazyLoadedClass {
+        private final String className;
+        private volatile boolean initialized;
+        private Class<?> cls;
+
+        LazyLoadedClass(String cn) {
+            className = cn;
+        }
+
+        synchronized Optional<Class<?>> load() {
+            if (!initialized) {
+                try {
+                    cls = ClassLoaderUtils.loadClass(className, ProviderFactory.class);
+                } catch (final Throwable ex) {
+                    LOG.fine(className + " not available, skipping");
+                }
+                initialized = true;
+            }
+
+            return Optional.ofNullable(cls);
+        }
+
+        boolean isAssignableFrom(Class<?> another) {
+            return load().map(c -> c.isAssignableFrom(another)).orElse(false);
+        }
+    }
 
     private JAXRSUtils() {
     }
@@ -242,7 +277,7 @@ public final class JAXRSUtils {
         return STREAMING_OUT_TYPES.contains(type) 
             || Closeable.class.isAssignableFrom(type)
             || Source.class.isAssignableFrom(type)
-            || DataSource.class.isAssignableFrom(type);
+            || DATA_SOURCE_CLASS.isAssignableFrom(type);
     }
 
     public static List<PathSegment> getPathSegments(String thePath, boolean decode) {