From b09835563256ea847dce090838564d43420d8f8e Mon Sep 17 00:00:00 2001 From: alanb Date: Thu, 4 Jul 2013 14:38:44 +0100 Subject: [PATCH] 8019622: (sl) ServiceLoader.next incorrect when creation and usages are in different contexts Reviewed-by: mchung, ahgross, forax, psandoz --- .../classes/java/util/ServiceLoader.java | 40 ++++++++++++++++--- 1 file changed, 34 insertions(+), 6 deletions(-) diff --git a/src/share/classes/java/util/ServiceLoader.java b/src/share/classes/java/util/ServiceLoader.java index 01a5f440f..962438022 100644 --- a/src/share/classes/java/util/ServiceLoader.java +++ b/src/share/classes/java/util/ServiceLoader.java @@ -30,6 +30,9 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URL; +import java.security.AccessController; +import java.security.AccessControlContext; +import java.security.PrivilegedAction; import java.util.ArrayList; import java.util.Enumeration; import java.util.Iterator; @@ -185,10 +188,13 @@ public final class ServiceLoader private static final String PREFIX = "META-INF/services/"; // The class or interface representing the service being loaded - private Class service; + private final Class service; // The class loader used to locate, load, and instantiate providers - private ClassLoader loader; + private final ClassLoader loader; + + // The access control context taken when the ServiceLoader is created + private final AccessControlContext acc; // Cached providers, in instantiation order private LinkedHashMap providers = new LinkedHashMap<>(); @@ -215,6 +221,7 @@ public final class ServiceLoader private ServiceLoader(Class svc, ClassLoader cl) { service = Objects.requireNonNull(svc, "Service interface cannot be null"); loader = (cl == null) ? ClassLoader.getSystemClassLoader() : cl; + acc = (System.getSecurityManager() != null) ? AccessController.getContext() : null; reload(); } @@ -327,7 +334,7 @@ public final class ServiceLoader this.loader = loader; } - public boolean hasNext() { + private boolean hasNextService() { if (nextName != null) { return true; } @@ -352,10 +359,9 @@ public final class ServiceLoader return true; } - public S next() { - if (!hasNext()) { + private S nextService() { + if (!hasNextService()) throw new NoSuchElementException(); - } String cn = nextName; nextName = null; Class c = null; @@ -381,6 +387,28 @@ public final class ServiceLoader throw new Error(); // This cannot happen } + public boolean hasNext() { + if (acc == null) { + return hasNextService(); + } else { + PrivilegedAction action = new PrivilegedAction() { + public Boolean run() { return hasNextService(); } + }; + return AccessController.doPrivileged(action, acc); + } + } + + public S next() { + if (acc == null) { + return nextService(); + } else { + PrivilegedAction action = new PrivilegedAction() { + public S run() { return nextService(); } + }; + return AccessController.doPrivileged(action, acc); + } + } + public void remove() { throw new UnsupportedOperationException(); } -- GitLab