From de9a3e66747e0e58f29d153becbfde15f1eb97f6 Mon Sep 17 00:00:00 2001 From: jmehrens Date: Fri, 22 Dec 2023 15:46:19 -0600 Subject: [PATCH 1/6] Jakarta Activation erroneously assumes that classes can be loaded from Thread#getContextClassLoader Signed-off-by: jmehrens --- .../jakarta/activation/FactoryFinder.java | 163 +++++++++++------- .../jakarta/activation/MailcapCommandMap.java | 8 +- .../activation/MimetypesFileTypeMap.java | 8 +- .../jakarta/activation/ServiceLoaderUtil.java | 30 +--- 4 files changed, 109 insertions(+), 100 deletions(-) diff --git a/api/src/main/java/jakarta/activation/FactoryFinder.java b/api/src/main/java/jakarta/activation/FactoryFinder.java index ca910c0..53e76d8 100644 --- a/api/src/main/java/jakarta/activation/FactoryFinder.java +++ b/api/src/main/java/jakarta/activation/FactoryFinder.java @@ -13,6 +13,7 @@ import java.lang.reflect.Method; import java.security.AccessController; import java.security.PrivilegedAction; +import java.util.Arrays; import java.util.Iterator; import java.util.logging.Level; import java.util.logging.Logger; @@ -32,41 +33,34 @@ public RuntimeException createException(Throwable throwable, String message) { /** * Finds the implementation {@code Class} object for the given - * factory type. If it fails and {@code tryFallback} is {@code true} - * finds the {@code Class} object for the given default class name. - * The arguments supplied must be used in order - * Note the default class name may be needed even if fallback - * is not to be attempted in order to check if requested type is fallback. + * factory type. *

* This method is package private so that this code can be shared. * * @param factoryClass factory abstract class or interface to be found - * @param defaultClassName the implementation class name, which is - * to be used only if nothing else - * is found; {@code null} to indicate - * that there is no default class name - * @param tryFallback whether to try the default class as a - * fallback * @return the {@code Class} object of the specified message factory; * may not be {@code null} * @throws RuntimeException if there is no factory found */ - static T find(Class factoryClass, - String defaultClassName, - boolean tryFallback) throws RuntimeException { - - ClassLoader tccl = ServiceLoaderUtil.contextClassLoader(EXCEPTION_HANDLER); - String factoryId = factoryClass.getName(); + static T find(Class factoryClass) throws RuntimeException { + for (ClassLoader l : getClassLoaders( + Thread.class, + FactoryFinder.class, + System.class)) { + T f = find(factoryClass, l); + if (f != null) { + return f; + } + } + throw new RuntimeException( + "Provider for " + factoryClass.getName() + " cannot be found", null); + } + static T find(Class factoryClass, ClassLoader loader) throws RuntimeException { // Use the system property first - String className = fromSystemProperty(factoryId); + String className = fromSystemProperty(factoryClass.getName()); if (className != null) { - T result = newInstance(className, defaultClassName, tccl); - if (result != null) { - return result; - } - // try api loader - result = newInstance(className, defaultClassName, FactoryFinder.class.getClassLoader()); + T result = newInstance(className, factoryClass, loader); if (result != null) { return result; } @@ -75,6 +69,7 @@ static T find(Class factoryClass, // standard services: java.util.ServiceLoader T factory = ServiceLoaderUtil.firstByServiceLoader( factoryClass, + loader, logger, EXCEPTION_HANDLER); if (factory != null) { @@ -82,33 +77,19 @@ static T find(Class factoryClass, } // handling Glassfish/OSGi (platform specific default) - if (isOsgi()) { - T result = lookupUsingOSGiServiceLoader(factoryId); - if (result != null) { - return result; - } + T result = lookupUsingHk2ServiceLoader(factoryClass, loader); + if (result != null) { + return result; } - // If not found and fallback should not be tried, throw RuntimeException. - if (!tryFallback) { - throw new RuntimeException( - "Provider for " + factoryId + " cannot be found", null); - } - - // We didn't find the class through the usual means so try the default - // (built in) factory if specified. - if (defaultClassName == null) { - throw new RuntimeException( - "Provider for " + factoryId + " cannot be found", null); - } - return newInstance(defaultClassName, defaultClassName, tccl); + return null; } - private static T newInstance(String className, String defaultClassName, ClassLoader tccl) throws RuntimeException { + private static T newInstance(String className, Class service, ClassLoader loader) throws RuntimeException { return ServiceLoaderUtil.newInstance( className, - defaultClassName, - tccl, + service, + loader, EXCEPTION_HANDLER); } @@ -136,31 +117,85 @@ private static void logFound(String value) { } } - private static final String OSGI_SERVICE_LOADER_CLASS_NAME = "org.glassfish.hk2.osgiresourcelocator.ServiceLoader"; + private static Class[] getHk2ServiceLoaderTargets(Class factoryClass) { + ClassLoader[] loaders = getClassLoaders(Thread.class, factoryClass, System.class); + + Class[] classes = new Class[loaders.length]; + int w = 0; + for (ClassLoader loader : loaders) { + if (loader != null) { + try { + classes[w++] = Class.forName("org.glassfish.hk2.osgiresourcelocator.ServiceLoader", false, loader); + } catch (Exception | LinkageError ignored) { + } //GlassFish class loaders can throw undocumented exceptions + } + } - private static boolean isOsgi() { - try { - Class.forName(OSGI_SERVICE_LOADER_CLASS_NAME); - return true; - } catch (ClassNotFoundException ignored) { + if (classes.length != w) { + classes = Arrays.copyOf(classes, w); } - return false; + return classes; } @SuppressWarnings({"unchecked"}) - private static T lookupUsingOSGiServiceLoader(String factoryId) { - try { - // Use reflection to avoid having any dependency on HK2 ServiceLoader class - Class serviceClass = Class.forName(factoryId); - Class[] args = new Class[]{serviceClass}; - Class target = Class.forName(OSGI_SERVICE_LOADER_CLASS_NAME); - Method m = target.getMethod("lookupProviderInstances", Class.class); - Iterator iter = ((Iterable) m.invoke(null, (Object[]) args)).iterator(); - return iter.hasNext() ? (T) iter.next() : null; - } catch (Exception ignored) { - // log and continue - return null; + private static T lookupUsingHk2ServiceLoader(Class factoryClass, ClassLoader loader) { + for (Class target : getHk2ServiceLoaderTargets(factoryClass)) { + try { + // Use reflection to avoid having any dependency on HK2 ServiceLoader class + Class serviceClass = Class.forName(factoryClass.getName(), false, loader); + Class[] args = new Class[]{serviceClass}; + Method m = target.getMethod("lookupProviderInstances", Class.class); + Iterable iterable = ((Iterable) m.invoke(null, (Object[]) args)); + if (iterable != null) { + Iterator iter = iterable.iterator(); + if (iter.hasNext()) { + return factoryClass.cast(iter.next()); //Verify classloader. + } + } + } catch (Exception ignored) { + // log and continue + } } + return null; } + private static ClassLoader[] getClassLoaders(final Class... classes) { + return AccessController.doPrivileged( + new PrivilegedAction() { + @Override + public ClassLoader[] run() { + ClassLoader[] loaders = new ClassLoader[classes.length]; + int w = 0; + for (Class k : classes) { + ClassLoader cl = null; + if (k == Thread.class) { + try { + cl = Thread.currentThread().getContextClassLoader(); + } catch (SecurityException ex) { + } + } else if (k == System.class) { + try { + cl = ClassLoader.getSystemClassLoader(); + } catch (SecurityException ex) { + } + } else { + try { + cl = k.getClassLoader(); + } catch (SecurityException ex) { + } + } + + if (cl != null) { + loaders[w++] = cl; + } + } + + if (loaders.length != w) { + loaders = Arrays.copyOf(loaders, w); + } + return loaders; + } + } + ); + } } diff --git a/api/src/main/java/jakarta/activation/MailcapCommandMap.java b/api/src/main/java/jakarta/activation/MailcapCommandMap.java index ba1cbe8..6fbb48e 100644 --- a/api/src/main/java/jakarta/activation/MailcapCommandMap.java +++ b/api/src/main/java/jakarta/activation/MailcapCommandMap.java @@ -706,15 +706,11 @@ private MailcapRegistryProvider getImplementation() { if (System.getSecurityManager() != null) { return AccessController.doPrivileged(new PrivilegedAction() { public MailcapRegistryProvider run() { - return FactoryFinder.find(MailcapRegistryProvider.class, - null, - false); + return FactoryFinder.find(MailcapRegistryProvider.class); } }); } else { - return FactoryFinder.find(MailcapRegistryProvider.class, - null, - false); + return FactoryFinder.find(MailcapRegistryProvider.class); } } diff --git a/api/src/main/java/jakarta/activation/MimetypesFileTypeMap.java b/api/src/main/java/jakarta/activation/MimetypesFileTypeMap.java index 17851ee..80a1d01 100644 --- a/api/src/main/java/jakarta/activation/MimetypesFileTypeMap.java +++ b/api/src/main/java/jakarta/activation/MimetypesFileTypeMap.java @@ -398,15 +398,11 @@ private MimeTypeRegistryProvider getImplementation() { if (System.getSecurityManager() != null) { return AccessController.doPrivileged(new PrivilegedAction() { public MimeTypeRegistryProvider run() { - return FactoryFinder.find(MimeTypeRegistryProvider.class, - null, - false); + return FactoryFinder.find(MimeTypeRegistryProvider.class); } }); } else { - return FactoryFinder.find(MimeTypeRegistryProvider.class, - null, - false); + return FactoryFinder.find(MimeTypeRegistryProvider.class); } } diff --git a/api/src/main/java/jakarta/activation/ServiceLoaderUtil.java b/api/src/main/java/jakarta/activation/ServiceLoaderUtil.java index 31854e6..376ad41 100644 --- a/api/src/main/java/jakarta/activation/ServiceLoaderUtil.java +++ b/api/src/main/java/jakarta/activation/ServiceLoaderUtil.java @@ -23,12 +23,13 @@ class ServiceLoaderUtil { static P firstByServiceLoader(Class

spiClass, + ClassLoader loader, Logger logger, ExceptionHandler handler) throws T { logger.log(Level.FINE, "Using java.util.ServiceLoader to find {0}", spiClass.getName()); // service discovery try { - ServiceLoader

serviceLoader = ServiceLoader.load(spiClass); + ServiceLoader

serviceLoader = ServiceLoader.load(spiClass, loader); for (P impl : serviceLoader) { logger.log(Level.FINE, "ServiceProvider loading Facility used; returning object [{0}]", impl.getClass().getName()); @@ -65,11 +66,11 @@ static

Class

nullSafeLoadClass(String className, ClassLoader classLoader) // unless it is defaultClassname. It means if you are trying to instantiate // default implementation (fallback), pass the class name to both first and second parameter. static P newInstance(String className, - String defaultImplClassName, ClassLoader classLoader, + Class

service, ClassLoader classLoader, final ExceptionHandler handler) throws T { try { - Class

cls = safeLoadClass(className, defaultImplClassName, classLoader); - return cls.getConstructor().newInstance(); + Class

cls = safeLoadClass(className, classLoader); + return service.cast(cls.getConstructor().newInstance()); } catch (ClassNotFoundException x) { throw handler.createException(x, "Provider " + className + " not found"); } catch (Exception x) { @@ -79,30 +80,11 @@ static P newInstance(String className, @SuppressWarnings({"unchecked"}) static

Class

safeLoadClass(String className, - String defaultImplClassName, ClassLoader classLoader) throws ClassNotFoundException { - - try { - checkPackageAccess(className); - } catch (SecurityException se) { - // anyone can access the platform default factory class without permission - if (defaultImplClassName != null && defaultImplClassName.equals(className)) { - return (Class

) Class.forName(className); - } - // not platform default implementation ... - throw se; - } + checkPackageAccess(className); return nullSafeLoadClass(className, classLoader); } - static ClassLoader contextClassLoader(ExceptionHandler exceptionHandler) throws T { - try { - return Thread.currentThread().getContextClassLoader(); - } catch (Exception x) { - throw exceptionHandler.createException(x, x.toString()); - } - } - static abstract class ExceptionHandler { public abstract T createException(Throwable throwable, String message); From 31fc4148a7945661a9d79d59d1cca5482464a168 Mon Sep 17 00:00:00 2001 From: jmehrens Date: Tue, 9 Jan 2024 01:12:49 -0600 Subject: [PATCH 2/6] Match serviceloader on null Signed-off-by: jmehrens --- .../java/jakarta/activation/ServiceLoaderUtil.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/api/src/main/java/jakarta/activation/ServiceLoaderUtil.java b/api/src/main/java/jakarta/activation/ServiceLoaderUtil.java index 376ad41..bcb609d 100644 --- a/api/src/main/java/jakarta/activation/ServiceLoaderUtil.java +++ b/api/src/main/java/jakarta/activation/ServiceLoaderUtil.java @@ -23,7 +23,7 @@ class ServiceLoaderUtil { static P firstByServiceLoader(Class

spiClass, - ClassLoader loader, + ClassLoader loader, Logger logger, ExceptionHandler handler) throws T { logger.log(Level.FINE, "Using java.util.ServiceLoader to find {0}", spiClass.getName()); @@ -55,16 +55,13 @@ static void checkPackageAccess(String className) { @SuppressWarnings({"unchecked"}) static

Class

nullSafeLoadClass(String className, ClassLoader classLoader) throws ClassNotFoundException { - if (classLoader == null) { - return (Class

) Class.forName(className); - } else { - return (Class

) classLoader.loadClass(className); + if (classLoader == null) { //Match behavior of ServiceLoader + classLoader = ClassLoader.getSystemClassLoader(); } + return (Class

) Class.forName(className, false, classLoader); } - // Returns instance of required class. It checks package access (security) - // unless it is defaultClassname. It means if you are trying to instantiate - // default implementation (fallback), pass the class name to both first and second parameter. + // Returns instance of required class. It checks package access (security). static P newInstance(String className, Class

service, ClassLoader classLoader, final ExceptionHandler handler) throws T { From b5c95c5d6c732307e6b654e4cd25899f4386863b Mon Sep 17 00:00:00 2001 From: jmehrens Date: Sun, 11 Feb 2024 23:49:53 -0600 Subject: [PATCH 3/6] Jakarta Activation erroneously assumes that classes can be loaded from Thread#getContextClassLoader #144 Signed-off-by: jmehrens --- .../jakarta/activation/FactoryFinder.java | 67 ++++++++++--------- .../jakarta/activation/MailcapCommandMap.java | 12 ++-- .../activation/MimetypesFileTypeMap.java | 12 ++-- 3 files changed, 47 insertions(+), 44 deletions(-) diff --git a/api/src/main/java/jakarta/activation/FactoryFinder.java b/api/src/main/java/jakarta/activation/FactoryFinder.java index 53e76d8..57bd290 100644 --- a/api/src/main/java/jakarta/activation/FactoryFinder.java +++ b/api/src/main/java/jakarta/activation/FactoryFinder.java @@ -27,7 +27,7 @@ class FactoryFinder { new ServiceLoaderUtil.ExceptionHandler() { @Override public RuntimeException createException(Throwable throwable, String message) { - return new RuntimeException(message, throwable); + return new IllegalStateException(message, throwable); } }; @@ -52,8 +52,9 @@ static T find(Class factoryClass) throws RuntimeException { return f; } } - throw new RuntimeException( - "Provider for " + factoryClass.getName() + " cannot be found", null); + + throw EXCEPTION_HANDLER.createException((Throwable) null, + "Provider for " + factoryClass.getName() + " cannot be found"); } static T find(Class factoryClass, ClassLoader loader) throws RuntimeException { @@ -85,7 +86,9 @@ static T find(Class factoryClass, ClassLoader loader) throws RuntimeExcep return null; } - private static T newInstance(String className, Class service, ClassLoader loader) throws RuntimeException { + private static T newInstance(String className, + Class service, ClassLoader loader) + throws RuntimeException { return ServiceLoaderUtil.newInstance( className, service, @@ -161,41 +164,41 @@ private static T lookupUsingHk2ServiceLoader(Class factoryClass, ClassLoa private static ClassLoader[] getClassLoaders(final Class... classes) { return AccessController.doPrivileged( - new PrivilegedAction() { - @Override - public ClassLoader[] run() { - ClassLoader[] loaders = new ClassLoader[classes.length]; - int w = 0; - for (Class k : classes) { - ClassLoader cl = null; - if (k == Thread.class) { - try { - cl = Thread.currentThread().getContextClassLoader(); - } catch (SecurityException ex) { - } - } else if (k == System.class) { - try { - cl = ClassLoader.getSystemClassLoader(); - } catch (SecurityException ex) { - } - } else { - try { - cl = k.getClassLoader(); - } catch (SecurityException ex) { - } + new PrivilegedAction() { + @Override + public ClassLoader[] run() { + ClassLoader[] loaders = new ClassLoader[classes.length]; + int w = 0; + for (Class k : classes) { + ClassLoader cl = null; + if (k == Thread.class) { + try { + cl = Thread.currentThread().getContextClassLoader(); + } catch (SecurityException ex) { } - - if (cl != null) { - loaders[w++] = cl; + } else if (k == System.class) { + try { + cl = ClassLoader.getSystemClassLoader(); + } catch (SecurityException ex) { + } + } else { + try { + cl = k.getClassLoader(); + } catch (SecurityException ex) { } } - if (loaders.length != w) { - loaders = Arrays.copyOf(loaders, w); + if (cl != null) { + loaders[w++] = cl; } - return loaders; } + + if (loaders.length != w) { + loaders = Arrays.copyOf(loaders, w); + } + return loaders; } + } ); } } diff --git a/api/src/main/java/jakarta/activation/MailcapCommandMap.java b/api/src/main/java/jakarta/activation/MailcapCommandMap.java index 6fbb48e..3ebbff8 100644 --- a/api/src/main/java/jakarta/activation/MailcapCommandMap.java +++ b/api/src/main/java/jakarta/activation/MailcapCommandMap.java @@ -210,7 +210,7 @@ private MailcapRegistry loadResource(String name) { } catch (IOException | SecurityException e) { if (LogSupport.isLoggable()) LogSupport.log("MailcapCommandMap: can't load " + name, e); - } catch (NoSuchElementException | ServiceConfigurationError e) { + } catch (NoSuchElementException | IllegalStateException | ServiceConfigurationError e) { if (LogSupport.isLoggable()) { LogSupport.log("Cannot find or load an implementation for MailcapRegistryProvider. " + "MailcapRegistry: can't load " + name, e); @@ -261,7 +261,7 @@ private void loadAllResources(List v, String name) { if (LogSupport.isLoggable()) LogSupport.log("MailcapCommandMap: can't load " + url, ioex); - } catch (NoSuchElementException | ServiceConfigurationError e) { + } catch (NoSuchElementException | IllegalStateException | ServiceConfigurationError e) { if (LogSupport.isLoggable()) { LogSupport.log("Cannot find or load an implementation for MailcapRegistryProvider. " + "MailcapRegistry: can't load " + name, e); @@ -296,7 +296,7 @@ private MailcapRegistry loadFile(String name) { if (LogSupport.isLoggable()) { LogSupport.log("MailcapRegistry: can't load from file - " + name, e); } - } catch (NoSuchElementException | ServiceConfigurationError e) { + } catch (NoSuchElementException | IllegalStateException | ServiceConfigurationError e) { if (LogSupport.isLoggable()) { LogSupport.log("Cannot find or load an implementation for MailcapRegistryProvider. " + "MailcapRegistry: can't load " + name, e); @@ -317,7 +317,7 @@ public MailcapCommandMap(String fileName) throws IOException { if (DB[PROG] == null) { try { DB[PROG] = getImplementation().getByFileName(fileName); - } catch (NoSuchElementException | ServiceConfigurationError e) { + } catch (NoSuchElementException | IllegalStateException | ServiceConfigurationError e) { String message = "Cannot find or load an implementation for MailcapRegistryProvider. " + "MailcapRegistry: can't load " + fileName; if (LogSupport.isLoggable()) { @@ -346,7 +346,7 @@ public MailcapCommandMap(InputStream is) { DB[PROG] = getImplementation().getByInputStream(is); } catch (IOException ex) { // XXX - should throw it - } catch (NoSuchElementException | ServiceConfigurationError e) { + } catch (NoSuchElementException | IllegalStateException | ServiceConfigurationError e) { if (LogSupport.isLoggable()) { LogSupport.log("Cannot find or load an implementation for MailcapRegistryProvider." + "MailcapRegistry: can't load InputStream", e); @@ -547,7 +547,7 @@ public synchronized void addMailcap(String mail_cap) { DB[PROG] = getImplementation().getInMemory(); } DB[PROG].appendToMailcap(mail_cap); - } catch (NoSuchElementException | ServiceConfigurationError e) { + } catch (NoSuchElementException | IllegalStateException | ServiceConfigurationError e) { if (LogSupport.isLoggable()) { LogSupport.log("Cannot find or load an implementation for MailcapRegistryProvider. " + "MailcapRegistry: can't load", e); diff --git a/api/src/main/java/jakarta/activation/MimetypesFileTypeMap.java b/api/src/main/java/jakarta/activation/MimetypesFileTypeMap.java index 80a1d01..8dcea9b 100644 --- a/api/src/main/java/jakarta/activation/MimetypesFileTypeMap.java +++ b/api/src/main/java/jakarta/activation/MimetypesFileTypeMap.java @@ -166,7 +166,7 @@ private MimeTypeRegistry loadResource(String name) { } catch (IOException | SecurityException e) { if (LogSupport.isLoggable()) LogSupport.log("MimetypesFileTypeMap: can't load " + name, e); - } catch (NoSuchElementException | ServiceConfigurationError e) { + } catch (NoSuchElementException | IllegalStateException | ServiceConfigurationError e) { if (LogSupport.isLoggable()) { LogSupport.log("Cannot find or load an implementation for MimeTypeRegistryProvider." + "MimeTypeRegistry: can't load " + name, e); @@ -228,7 +228,7 @@ private void loadAllResources(Vector v, String name) { if (LogSupport.isLoggable()) LogSupport.log("MimetypesFileTypeMap: can't load " + url, ioex); - } catch (NoSuchElementException | ServiceConfigurationError e) { + } catch (NoSuchElementException | IllegalStateException | ServiceConfigurationError e) { if (LogSupport.isLoggable()) { LogSupport.log("Cannot find or load an implementation for MimeTypeRegistryProvider." + "MimeTypeRegistry: can't load " + url, e); @@ -270,7 +270,7 @@ private MimeTypeRegistry loadFile(String name) { if (LogSupport.isLoggable()) { LogSupport.log("MimeTypeRegistry: can't load from file - " + name, e); } - } catch (NoSuchElementException | ServiceConfigurationError e) { + } catch (NoSuchElementException | IllegalStateException | ServiceConfigurationError e) { if (LogSupport.isLoggable()) { LogSupport.log("Cannot find or load an implementation for MimeTypeRegistryProvider." + "MimeTypeRegistry: can't load " + name, e); @@ -290,7 +290,7 @@ public MimetypesFileTypeMap(String mimeTypeFileName) throws IOException { this(); try { DB[PROG] = getImplementation().getByFileName(mimeTypeFileName); - } catch (NoSuchElementException | ServiceConfigurationError e) { + } catch (NoSuchElementException | IllegalStateException | ServiceConfigurationError e) { String errorMessage = "Cannot find or load an implementation for MimeTypeRegistryProvider." + "MimeTypeRegistry: can't load " + mimeTypeFileName; if (LogSupport.isLoggable()) { @@ -312,7 +312,7 @@ public MimetypesFileTypeMap(InputStream is) { DB[PROG] = getImplementation().getByInputStream(is); } catch (IOException ex) { // XXX - really should throw it - } catch (NoSuchElementException | ServiceConfigurationError e) { + } catch (NoSuchElementException | IllegalStateException | ServiceConfigurationError e) { if (LogSupport.isLoggable()) { LogSupport.log("Cannot find or load an implementation for MimeTypeRegistryProvider." + "MimeTypeRegistry: can't load InputStream", e); @@ -332,7 +332,7 @@ public synchronized void addMimeTypes(String mime_types) { DB[PROG] = getImplementation().getInMemory(); } DB[PROG].appendToRegistry(mime_types); - } catch (NoSuchElementException | ServiceConfigurationError e) { + } catch (NoSuchElementException | IllegalStateException | ServiceConfigurationError e) { if (LogSupport.isLoggable()) { LogSupport.log("Cannot find or load an implementation for MimeTypeRegistryProvider." + "MimeTypeRegistry: can't add " + mime_types, e); From e957fbc3cbfbf306e63d77bffa70abd1273c45b3 Mon Sep 17 00:00:00 2001 From: jmehrens Date: Tue, 13 Feb 2024 23:17:02 -0600 Subject: [PATCH 4/6] Jakarta Activation erroneously assumes that classes can be loaded from Thread#getContextClassLoader #145 Signed-off-by: jmehrens --- api/src/main/java/jakarta/activation/FactoryFinder.java | 2 +- api/src/main/java/jakarta/activation/MailcapCommandMap.java | 2 +- .../main/java/jakarta/activation/MimetypesFileTypeMap.java | 2 +- api/src/main/java/jakarta/activation/ServiceLoaderUtil.java | 6 ++---- 4 files changed, 5 insertions(+), 7 deletions(-) diff --git a/api/src/main/java/jakarta/activation/FactoryFinder.java b/api/src/main/java/jakarta/activation/FactoryFinder.java index 57bd290..2e59542 100644 --- a/api/src/main/java/jakarta/activation/FactoryFinder.java +++ b/api/src/main/java/jakarta/activation/FactoryFinder.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0, which is available at diff --git a/api/src/main/java/jakarta/activation/MailcapCommandMap.java b/api/src/main/java/jakarta/activation/MailcapCommandMap.java index 3ebbff8..c9bb2bc 100644 --- a/api/src/main/java/jakarta/activation/MailcapCommandMap.java +++ b/api/src/main/java/jakarta/activation/MailcapCommandMap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0, which is available at diff --git a/api/src/main/java/jakarta/activation/MimetypesFileTypeMap.java b/api/src/main/java/jakarta/activation/MimetypesFileTypeMap.java index 8dcea9b..4853286 100644 --- a/api/src/main/java/jakarta/activation/MimetypesFileTypeMap.java +++ b/api/src/main/java/jakarta/activation/MimetypesFileTypeMap.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2023 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2024 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0, which is available at diff --git a/api/src/main/java/jakarta/activation/ServiceLoaderUtil.java b/api/src/main/java/jakarta/activation/ServiceLoaderUtil.java index bcb609d..f5960db 100644 --- a/api/src/main/java/jakarta/activation/ServiceLoaderUtil.java +++ b/api/src/main/java/jakarta/activation/ServiceLoaderUtil.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2021 Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2021, 2024 Oracle and/or its affiliates. All rights reserved. * * This program and the accompanying materials are made available under the * terms of the Eclipse Distribution License v. 1.0, which is available at @@ -15,8 +15,7 @@ import java.util.logging.Logger; /** - * Shared ServiceLoader/FactoryFinder Utils shared among JAF, MAIL, SAAJ, JAXB and JAXWS - * Class duplicated to all those projects. + * Shared ServiceLoader/FactoryFinder Utils. * * @author Miroslav.Kos@oracle.com */ @@ -87,5 +86,4 @@ static abstract class ExceptionHandler { public abstract T createException(Throwable throwable, String message); } - } From 29bd85b9ea184603a5198b80ab1a5f28a96c6ef1 Mon Sep 17 00:00:00 2001 From: jmehrens Date: Tue, 13 Feb 2024 23:21:57 -0600 Subject: [PATCH 5/6] Jakarta Activation erroneously assumes that classes can be loaded from Thread#getContextClassLoader #145 Signed-off-by: jmehrens --- api/src/main/java/jakarta/activation/ServiceLoaderUtil.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/api/src/main/java/jakarta/activation/ServiceLoaderUtil.java b/api/src/main/java/jakarta/activation/ServiceLoaderUtil.java index f5960db..dfeabdf 100644 --- a/api/src/main/java/jakarta/activation/ServiceLoaderUtil.java +++ b/api/src/main/java/jakarta/activation/ServiceLoaderUtil.java @@ -15,7 +15,9 @@ import java.util.logging.Logger; /** - * Shared ServiceLoader/FactoryFinder Utils. + * Shared ServiceLoader/FactoryFinder Utils. JAF and MAIL use the same loading + * logic of thread context class loader, calling class loader, and finally the + * system class loader. * * @author Miroslav.Kos@oracle.com */ From 41510885b144fc1da844488b29cb46768f0de3c7 Mon Sep 17 00:00:00 2001 From: jmehrens Date: Tue, 13 Feb 2024 23:26:56 -0600 Subject: [PATCH 6/6] Jakarta Activation erroneously assumes that classes can be loaded from Thread#getContextClassLoader #145 Signed-off-by: jmehrens --- api/src/main/java/jakarta/activation/FactoryFinder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/api/src/main/java/jakarta/activation/FactoryFinder.java b/api/src/main/java/jakarta/activation/FactoryFinder.java index 2e59542..2ddd801 100644 --- a/api/src/main/java/jakarta/activation/FactoryFinder.java +++ b/api/src/main/java/jakarta/activation/FactoryFinder.java @@ -40,7 +40,7 @@ public RuntimeException createException(Throwable throwable, String message) { * @param factoryClass factory abstract class or interface to be found * @return the {@code Class} object of the specified message factory; * may not be {@code null} - * @throws RuntimeException if there is no factory found + * @throws IllegalStateException if there is no factory found */ static T find(Class factoryClass) throws RuntimeException { for (ClassLoader l : getClassLoaders(