[1004] Wrap service loader calls in privileged actions if the security manager is enabled. Also ensure the LinkageError for the ClientBuilder is thrown if a security manager is enabled. (#1005)
Resolves #1004
Signed-off-by: James R. Perkins <jperkins@redhat.com>
diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/client/ClientBuilder.java b/jaxrs-api/src/main/java/jakarta/ws/rs/client/ClientBuilder.java
index b07c2ba..7bf0237 100644
--- a/jaxrs-api/src/main/java/jakarta/ws/rs/client/ClientBuilder.java
+++ b/jaxrs-api/src/main/java/jakarta/ws/rs/client/ClientBuilder.java
@@ -19,7 +19,9 @@
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLContext;
import java.net.URL;
+import java.security.AccessController;
import java.security.KeyStore;
+import java.security.PrivilegedAction;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
@@ -59,16 +61,14 @@
try {
Object delegate = FactoryFinder.find(JAXRS_DEFAULT_CLIENT_BUILDER_PROPERTY, ClientBuilder.class);
if (!(delegate instanceof ClientBuilder)) {
- Class pClass = ClientBuilder.class;
- String classnameAsResource = pClass.getName().replace('.', '/') + ".class";
- ClassLoader loader = pClass.getClassLoader();
- if (loader == null) {
- loader = ClassLoader.getSystemClassLoader();
+ final CreateErrorMessageAction action = new CreateErrorMessageAction(delegate);
+ final String errorMessage;
+ if (System.getSecurityManager() == null) {
+ errorMessage = action.run();
+ } else {
+ errorMessage = AccessController.doPrivileged(action);
}
- URL targetTypeURL = loader.getResource(classnameAsResource);
- throw new LinkageError("ClassCastException: attempting to cast"
- + delegate.getClass().getClassLoader().getResource(classnameAsResource)
- + " to " + targetTypeURL);
+ throw new LinkageError(errorMessage);
}
return (ClientBuilder) delegate;
} catch (Exception ex) {
@@ -271,4 +271,26 @@
* @return a new client instance.
*/
public abstract Client build();
+
+ private static class CreateErrorMessageAction implements PrivilegedAction<String> {
+ private final Object delegate;
+
+ private CreateErrorMessageAction(final Object delegate) {
+ this.delegate = delegate;
+ }
+
+ @Override
+ public String run() {
+ Class<?> pClass = ClientBuilder.class;
+ String classnameAsResource = pClass.getName().replace('.', '/') + ".class";
+ ClassLoader loader = pClass.getClassLoader();
+ if (loader == null) {
+ loader = ClassLoader.getSystemClassLoader();
+ }
+ URL targetTypeURL = loader.getResource(classnameAsResource);
+ return "ClassCastException: attempting to cast"
+ + delegate.getClass().getClassLoader().getResource(classnameAsResource)
+ + " to " + targetTypeURL;
+ }
+ }
}
diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/client/FactoryFinder.java b/jaxrs-api/src/main/java/jakarta/ws/rs/client/FactoryFinder.java
index 9801cd8..74deb05 100644
--- a/jaxrs-api/src/main/java/jakarta/ws/rs/client/FactoryFinder.java
+++ b/jaxrs-api/src/main/java/jakarta/ws/rs/client/FactoryFinder.java
@@ -21,9 +21,7 @@
import java.io.IOException;
import java.security.AccessController;
import java.security.PrivilegedAction;
-import java.util.Iterator;
import java.util.Properties;
-import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -45,6 +43,11 @@
}
static ClassLoader getContextClassLoader() {
+ // For performance reasons, check if a security manager is installed. If not there is no need to use a
+ // privileged action.
+ if (System.getSecurityManager() == null) {
+ return Thread.currentThread().getContextClassLoader();
+ }
return AccessController.doPrivileged((PrivilegedAction<ClassLoader>) () -> {
ClassLoader cl = null;
try {
@@ -107,24 +110,16 @@
static <T> Object find(final String factoryId, final Class<T> service) throws ClassNotFoundException {
ClassLoader classLoader = getContextClassLoader();
- try {
- Iterator<T> iterator = ServiceLoader.load(service, FactoryFinder.getContextClassLoader()).iterator();
-
- if (iterator.hasNext()) {
- return iterator.next();
- }
- } catch (Exception | ServiceConfigurationError ex) {
- LOGGER.log(Level.FINER, "Failed to load service " + factoryId + ".", ex);
+ // First try the TCCL
+ Object result = findFirstService(factoryId, classLoader, service);
+ if (result != null) {
+ return result;
}
- try {
- Iterator<T> iterator = ServiceLoader.load(service, FactoryFinder.class.getClassLoader()).iterator();
-
- if (iterator.hasNext()) {
- return iterator.next();
- }
- } catch (Exception | ServiceConfigurationError ex) {
- LOGGER.log(Level.FINER, "Failed to load service " + factoryId + ".", ex);
+ // Next try the class loader from the FactoryFinder
+ result = findFirstService(factoryId, getClassLoader(), service);
+ if (result != null) {
+ return result;
}
// try to read from $java.home/lib/jaxrs.properties
@@ -168,4 +163,29 @@
throw new ClassNotFoundException(
"Provider for " + factoryId + " cannot be found", null);
}
+
+ private static ClassLoader getClassLoader() {
+ if (System.getSecurityManager() == null) {
+ return FactoryFinder.class.getClassLoader();
+ }
+ return AccessController.doPrivileged((PrivilegedAction<ClassLoader>) FactoryFinder.class::getClassLoader);
+ }
+
+ private static <T> T findFirstService(final String factoryId, final ClassLoader cl, final Class<T> service) {
+ final PrivilegedAction<T> action = () -> {
+ try {
+ final ServiceLoader<T> loader = ServiceLoader.load(service, cl);
+ if (loader.iterator().hasNext()) {
+ return loader.iterator().next();
+ }
+ } catch (Exception e) {
+ LOGGER.log(Level.FINER, "Failed to load service " + factoryId + ".", e);
+ }
+ return null;
+ };
+ if (System.getSecurityManager() == null) {
+ return action.run();
+ }
+ return AccessController.doPrivileged(action);
+ }
}
diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/ext/FactoryFinder.java b/jaxrs-api/src/main/java/jakarta/ws/rs/ext/FactoryFinder.java
index d3a91c8..bbd5afd 100644
--- a/jaxrs-api/src/main/java/jakarta/ws/rs/ext/FactoryFinder.java
+++ b/jaxrs-api/src/main/java/jakarta/ws/rs/ext/FactoryFinder.java
@@ -21,9 +21,7 @@
import java.io.IOException;
import java.security.AccessController;
import java.security.PrivilegedAction;
-import java.util.Iterator;
import java.util.Properties;
-import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -45,6 +43,11 @@
}
private static ClassLoader getContextClassLoader() {
+ // For performance reasons, check if a security manager is installed. If not there is no need to use a
+ // privileged action.
+ if (System.getSecurityManager() == null) {
+ return Thread.currentThread().getContextClassLoader();
+ }
return AccessController.doPrivileged((PrivilegedAction<ClassLoader>) () -> {
ClassLoader cl = null;
try {
@@ -107,24 +110,16 @@
static <T> Object find(final String factoryId, final Class<T> service) throws ClassNotFoundException {
ClassLoader classLoader = getContextClassLoader();
- try {
- Iterator<T> iterator = ServiceLoader.load(service, FactoryFinder.getContextClassLoader()).iterator();
-
- if (iterator.hasNext()) {
- return iterator.next();
- }
- } catch (Exception | ServiceConfigurationError ex) {
- LOGGER.log(Level.FINER, "Failed to load service " + factoryId + ".", ex);
+ // First try the TCCL
+ Object result = findFirstService(factoryId, classLoader, service);
+ if (result != null) {
+ return result;
}
- try {
- Iterator<T> iterator = ServiceLoader.load(service, FactoryFinder.class.getClassLoader()).iterator();
-
- if (iterator.hasNext()) {
- return iterator.next();
- }
- } catch (Exception | ServiceConfigurationError ex) {
- LOGGER.log(Level.FINER, "Failed to load service " + factoryId + ".", ex);
+ // Next try the class loader from the FactoryFinder
+ result = findFirstService(factoryId, getClassLoader(), service);
+ if (result != null) {
+ return result;
}
// try to read from $java.home/lib/jaxrs.properties
@@ -168,4 +163,29 @@
throw new ClassNotFoundException(
"Provider for " + factoryId + " cannot be found", null);
}
+
+ private static ClassLoader getClassLoader() {
+ if (System.getSecurityManager() == null) {
+ return FactoryFinder.class.getClassLoader();
+ }
+ return AccessController.doPrivileged((PrivilegedAction<ClassLoader>) FactoryFinder.class::getClassLoader);
+ }
+
+ private static <T> T findFirstService(final String factoryId, final ClassLoader cl, final Class<T> service) {
+ final PrivilegedAction<T> action = () -> {
+ try {
+ final ServiceLoader<T> loader = ServiceLoader.load(service, cl);
+ if (loader.iterator().hasNext()) {
+ return loader.iterator().next();
+ }
+ } catch (Exception e) {
+ LOGGER.log(Level.FINER, "Failed to load service " + factoryId + ".", e);
+ }
+ return null;
+ };
+ if (System.getSecurityManager() == null) {
+ return action.run();
+ }
+ return AccessController.doPrivileged(action);
+ }
}
diff --git a/jaxrs-api/src/main/java/jakarta/ws/rs/sse/FactoryFinder.java b/jaxrs-api/src/main/java/jakarta/ws/rs/sse/FactoryFinder.java
index fa614af..40440ae 100644
--- a/jaxrs-api/src/main/java/jakarta/ws/rs/sse/FactoryFinder.java
+++ b/jaxrs-api/src/main/java/jakarta/ws/rs/sse/FactoryFinder.java
@@ -21,9 +21,7 @@
import java.io.IOException;
import java.security.AccessController;
import java.security.PrivilegedAction;
-import java.util.Iterator;
import java.util.Properties;
-import java.util.ServiceConfigurationError;
import java.util.ServiceLoader;
import java.util.logging.Level;
import java.util.logging.Logger;
@@ -45,6 +43,11 @@
}
private static ClassLoader getContextClassLoader() {
+ // For performance reasons, check if a security manager is installed. If not there is no need to use a
+ // privileged action.
+ if (System.getSecurityManager() == null) {
+ return Thread.currentThread().getContextClassLoader();
+ }
return AccessController.doPrivileged((PrivilegedAction<ClassLoader>) () -> {
ClassLoader cl = null;
try {
@@ -107,24 +110,16 @@
static <T> Object find(final String factoryId, final Class<T> service) throws ClassNotFoundException {
ClassLoader classLoader = getContextClassLoader();
- try {
- Iterator<T> iterator = ServiceLoader.load(service, FactoryFinder.getContextClassLoader()).iterator();
-
- if (iterator.hasNext()) {
- return iterator.next();
- }
- } catch (Exception | ServiceConfigurationError ex) {
- LOGGER.log(Level.FINER, "Failed to load service " + factoryId + ".", ex);
+ // First try the TCCL
+ Object result = findFirstService(factoryId, classLoader, service);
+ if (result != null) {
+ return result;
}
- try {
- Iterator<T> iterator = ServiceLoader.load(service, FactoryFinder.class.getClassLoader()).iterator();
-
- if (iterator.hasNext()) {
- return iterator.next();
- }
- } catch (Exception | ServiceConfigurationError ex) {
- LOGGER.log(Level.FINER, "Failed to load service " + factoryId + ".", ex);
+ // Next try the class loader from the FactoryFinder
+ result = findFirstService(factoryId, getClassLoader(), service);
+ if (result != null) {
+ return result;
}
// try to read from $java.home/lib/jaxrs.properties
@@ -168,4 +163,29 @@
throw new ClassNotFoundException(
"Provider for " + factoryId + " cannot be found", null);
}
+
+ private static ClassLoader getClassLoader() {
+ if (System.getSecurityManager() == null) {
+ return FactoryFinder.class.getClassLoader();
+ }
+ return AccessController.doPrivileged((PrivilegedAction<ClassLoader>) FactoryFinder.class::getClassLoader);
+ }
+
+ private static <T> T findFirstService(final String factoryId, final ClassLoader cl, final Class<T> service) {
+ final PrivilegedAction<T> action = () -> {
+ try {
+ final ServiceLoader<T> loader = ServiceLoader.load(service, cl);
+ if (loader.iterator().hasNext()) {
+ return loader.iterator().next();
+ }
+ } catch (Exception e) {
+ LOGGER.log(Level.FINER, "Failed to load service " + factoryId + ".", e);
+ }
+ return null;
+ };
+ if (System.getSecurityManager() == null) {
+ return action.run();
+ }
+ return AccessController.doPrivileged(action);
+ }
}