8323624: ProviderList.ServiceList does not need to be a list

Reviewed-by: mullan
This commit is contained in:
Weijun Wang 2024-03-29 15:23:26 +00:00
parent 418deaf5a1
commit 59c2aff1ed
12 changed files with 70 additions and 131 deletions

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -131,8 +131,7 @@ public class KeyFactory {
private KeyFactory(String algorithm) throws NoSuchAlgorithmException {
this.algorithm = algorithm;
List<Service> list = GetInstance.getServices("KeyFactory", algorithm);
serviceIterator = list.iterator();
serviceIterator = GetInstance.getServices("KeyFactory", algorithm);
// fetch and instantiate initial spi
if (nextSpi(null) == null) {
throw new NoSuchAlgorithmException

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -230,9 +230,7 @@ public abstract class KeyPairGenerator extends KeyPairGeneratorSpi {
public static KeyPairGenerator getInstance(String algorithm)
throws NoSuchAlgorithmException {
Objects.requireNonNull(algorithm, "null algorithm name");
List<Service> list =
GetInstance.getServices("KeyPairGenerator", algorithm);
Iterator<Service> t = list.iterator();
Iterator<Service> t = GetInstance.getServices("KeyPairGenerator", algorithm);
if (!t.hasNext()) {
throw new NoSuchAlgorithmException
(algorithm + " KeyPairGenerator not available");

@ -1,5 +1,5 @@
/*
* Copyright (c) 1996, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1996, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -257,13 +257,12 @@ public abstract class Signature extends SignatureSpi {
public static Signature getInstance(String algorithm)
throws NoSuchAlgorithmException {
Objects.requireNonNull(algorithm, "null algorithm name");
List<Service> list;
Iterator<Service> t;
if (algorithm.equalsIgnoreCase(RSA_SIGNATURE)) {
list = GetInstance.getServices(rsaIds);
t = GetInstance.getServices(rsaIds);
} else {
list = GetInstance.getServices("Signature", algorithm);
t = GetInstance.getServices("Signature", algorithm);
}
Iterator<Service> t = list.iterator();
if (!t.hasNext()) {
throw new NoSuchAlgorithmException
(algorithm + " Signature not available");

@ -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.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -539,10 +539,9 @@ public class Cipher {
for (Transform transform : transforms) {
cipherServices.add(new ServiceId("Cipher", transform.transform));
}
List<Service> services = GetInstance.getServices(cipherServices);
// make sure there is at least one service from a signed provider
// and that it can use the specified mode and padding
Iterator<Service> t = services.iterator();
Iterator<Service> t = GetInstance.getServices(cipherServices);
Exception failure = null;
while (t.hasNext()) {
Service s = t.next();

@ -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.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -154,9 +154,10 @@ final class JceSecurity {
static Instance getInstance(String type, Class<?> clazz, String algorithm)
throws NoSuchAlgorithmException {
List<Service> services = GetInstance.getServices(type, algorithm);
Iterator<Service> t = GetInstance.getServices(type, algorithm);
NoSuchAlgorithmException failure = null;
for (Service s : services) {
while (t.hasNext()) {
Service s = t.next();
if (canUseProvider(s.getProvider()) == false) {
// allow only signed providers
continue;

@ -30,6 +30,7 @@ import java.security.*;
import java.security.InvalidAlgorithmParameterException;
import java.security.spec.AlgorithmParameterSpec;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Objects;
@ -537,11 +538,12 @@ public final class KEM {
*/
public static KEM getInstance(String algorithm)
throws NoSuchAlgorithmException {
List<Provider.Service> list = GetInstance.getServices(
Iterator<Provider.Service> t = GetInstance.getServices(
"KEM",
Objects.requireNonNull(algorithm, "null algorithm name"));
List<Provider.Service> allowed = new ArrayList<>();
for (Provider.Service s : list) {
while (t.hasNext()) {
Provider.Service s = t.next();
if (!JceSecurity.canUseProvider(s.getProvider())) {
continue;
}

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -180,10 +180,8 @@ public class KeyAgreement {
public static final KeyAgreement getInstance(String algorithm)
throws NoSuchAlgorithmException {
Objects.requireNonNull(algorithm, "null algorithm name");
List<Service> services =
GetInstance.getServices("KeyAgreement", algorithm);
// make sure there is at least one service from a signed provider
Iterator<Service> t = services.iterator();
Iterator<Service> t = GetInstance.getServices("KeyAgreement", algorithm);
while (t.hasNext()) {
Service s = t.next();
if (!JceSecurity.canUseProvider(s.getProvider())) {

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -167,9 +167,7 @@ public class KeyGenerator {
private KeyGenerator(String algorithm) throws NoSuchAlgorithmException {
this.algorithm = algorithm;
List<Service> list =
GetInstance.getServices("KeyGenerator", algorithm);
serviceIterator = list.iterator();
serviceIterator = GetInstance.getServices("KeyGenerator", algorithm);
initType = I_NONE;
// fetch and instantiate initial spi
if (nextSpi(null, false) == null) {

@ -1,5 +1,5 @@
/*
* Copyright (c) 1998, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1998, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -177,9 +177,8 @@ public class Mac implements Cloneable {
public static final Mac getInstance(String algorithm)
throws NoSuchAlgorithmException {
Objects.requireNonNull(algorithm, "null algorithm name");
List<Service> services = GetInstance.getServices("Mac", algorithm);
// make sure there is at least one service from a signed provider
Iterator<Service> t = services.iterator();
Iterator<Service> t = GetInstance.getServices("Mac", algorithm);
while (t.hasNext()) {
Service s = t.next();
if (!JceSecurity.canUseProvider(s.getProvider())) {

@ -1,5 +1,5 @@
/*
* Copyright (c) 1997, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -110,9 +110,7 @@ public class SecretKeyFactory {
private SecretKeyFactory(String algorithm) throws NoSuchAlgorithmException {
this.algorithm = algorithm;
List<Service> list =
GetInstance.getServices("SecretKeyFactory", algorithm);
serviceIterator = list.iterator();
serviceIterator = GetInstance.getServices("SecretKeyFactory", algorithm);
// fetch and instantiate initial spi
if (nextSpi(null) == null) {
throw new NoSuchAlgorithmException

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -104,33 +104,21 @@ public class GetInstance {
}
/**
* Return a List of all the available Services that implement
* (type, algorithm). Note that the list is initialized lazily
* Return an iterator over all the available Services that implement
* (type, algorithm). Note that the iterator is initialized lazily
* and Provider loading and lookup is only triggered when
* necessary.
*/
public static List<Service> getServices(String type, String algorithm) {
public static Iterator<Service> getServices(String type, String algorithm) {
ProviderList list = Providers.getProviderList();
return list.getServices(type, algorithm);
}
/**
* This method exists for compatibility with JCE only. It will be removed
* once JCE has been changed to use the replacement method.
* @deprecated use {@code getServices(List<ServiceId>)} instead
*/
@Deprecated
public static List<Service> getServices(String type,
List<String> algorithms) {
ProviderList list = Providers.getProviderList();
return list.getServices(type, algorithms);
}
/**
* Return a List of all the available Services that implement any of
* Return an iterator over all the available Services that implement any of
* the specified algorithms. See getServices(String, String) for details.
*/
public static List<Service> getServices(List<ServiceId> ids) {
public static Iterator<Service> getServices(List<ServiceId> ids) {
ProviderList list = Providers.getProviderList();
return list.getServices(ids);
}
@ -167,7 +155,9 @@ public class GetInstance {
}
// if we cannot get the service from the preferred provider,
// fail over to the next
for (Service s : list.getServices(type, algorithm)) {
Iterator<Service> services = list.getServices(type, algorithm);
while (services.hasNext()) {
Service s = services.next();
if (s == firstService) {
// do not retry initial failed service
continue;
@ -183,9 +173,10 @@ public class GetInstance {
public static Instance getInstance(String type, Class<?> clazz,
String algorithm, Object param) throws NoSuchAlgorithmException {
List<Service> services = getServices(type, algorithm);
Iterator<Service> services = getServices(type, algorithm);
NoSuchAlgorithmException failure = null;
for (Service s : services) {
while (services.hasNext()) {
Service s = services.next();
try {
return getInstance(s, clazz, param);
} catch (NoSuchAlgorithmException e) {

@ -1,5 +1,5 @@
/*
* Copyright (c) 2003, 2022, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2003, 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -391,42 +391,28 @@ public final class ProviderList {
}
/**
* Return a List containing all the Services describing implementations
* Return an iterator over all the Services describing implementations
* of the specified algorithms in precedence order. If no implementation
* exists, this method returns an empty List.
* exists, this method returns an empty iterator.
*
* The elements of this list are determined lazily on demand.
* The elements of this iterator are determined lazily on demand.
*
* The List returned is NOT thread safe.
* The iterator returned is NOT thread safe.
*/
public List<Service> getServices(String type, String algorithm) {
return new ServiceList(type, algorithm);
public Iterator<Service> getServices(String type, String algorithm) {
return new ServiceIterator(type, algorithm);
}
public Iterator<Service> getServices(List<ServiceId> ids) {
return new ServiceIterator(ids);
}
/**
* This method exists for compatibility with JCE only. It will be removed
* once JCE has been changed to use the replacement method.
* @deprecated use {@code getServices(List<ServiceId>)} instead
*/
@Deprecated
public List<Service> getServices(String type, List<String> algorithms) {
List<ServiceId> ids = new ArrayList<>();
for (String alg : algorithms) {
ids.add(new ServiceId(type, alg));
}
return getServices(ids);
}
public List<Service> getServices(List<ServiceId> ids) {
return new ServiceList(ids);
}
/**
* Inner class for a List of Services. Custom List implementation in
* Inner class for an iterator over Services. Customized implementation in
* order to delay Provider initialization and lookup.
* Not thread safe.
*/
private final class ServiceList extends AbstractList<Service> {
private final class ServiceIterator implements Iterator<Service> {
// type and algorithm for simple lookup
// avoid allocating/traversing the ServiceId list for these lookups
@ -449,17 +435,17 @@ public final class ProviderList {
// index into config[] of the next provider we need to query
private int providerIndex = 0;
// Matching preferred provider list for this ServiceList
// Matching preferred provider list for this ServiceIterator
ArrayList<PreferredEntry> preferredList = null;
private int preferredIndex = 0;
ServiceList(String type, String algorithm) {
ServiceIterator(String type, String algorithm) {
this.type = type;
this.algorithm = algorithm;
this.ids = null;
}
ServiceList(List<ServiceId> ids) {
ServiceIterator(List<ServiceId> ids) {
this.type = null;
this.algorithm = null;
this.ids = ids;
@ -534,55 +520,26 @@ public final class ProviderList {
}
}
public Service get(int index) {
int index;
@Override
public boolean hasNext() {
return tryGet(index) != null;
}
@Override
public Service next() {
Service s = tryGet(index);
if (s == null) {
throw new IndexOutOfBoundsException();
throw new NoSuchElementException();
}
index++;
return s;
}
public int size() {
int n;
if (services != null) {
n = services.size();
} else {
n = (firstService != null) ? 1 : 0;
}
while (tryGet(n) != null) {
n++;
}
return n;
}
// override isEmpty() and iterator() to not call size()
// this avoids loading + checking all Providers
public boolean isEmpty() {
return (tryGet(0) == null);
}
public Iterator<Service> iterator() {
return new Iterator<>() {
int index;
public boolean hasNext() {
return tryGet(index) != null;
}
public Service next() {
Service s = tryGet(index);
if (s == null) {
throw new NoSuchElementException();
}
index++;
return s;
}
public void remove() {
throw new UnsupportedOperationException();
}
};
@Override
public void remove() {
throw new UnsupportedOperationException();
}
}
@ -592,9 +549,9 @@ public final class ProviderList {
/*
* Return a list of all preferred entries that match the passed
* ServiceList.
* ServiceIterator.
*/
ArrayList<PreferredEntry> getAll(ServiceList s) {
ArrayList<PreferredEntry> getAll(ServiceIterator s) {
if (s.ids == null) {
return getAll(s.type, s.algorithm);