151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/* 251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved. 351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is free software; you can redistribute it and/or modify it 651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * under the terms of the GNU General Public License version 2 only, as 751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * published by the Free Software Foundation. Oracle designates this 851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * particular file as subject to the "Classpath" exception as provided 951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * by Oracle in the LICENSE file that accompanied this code. 1051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This code is distributed in the hope that it will be useful, but WITHOUT 1251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 1351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 1451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * version 2 for more details (a copy is included in the LICENSE file that 1551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * accompanied this code). 1651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 1751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * You should have received a copy of the GNU General Public License version 1851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2 along with this work; if not, write to the Free Software Foundation, 1951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 2051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 2151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 2251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * or visit www.oracle.com if you need additional information or have any 2351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * questions. 2451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 2551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipackage sun.security.jca; 2751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 2851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.util.*; 2951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.*; 3151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskiimport java.security.Provider.Service; 3251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 3351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski/** 3451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * List of Providers. Used to represent the provider preferences. 3551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 3651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The system starts out with a ProviderList that only has the classNames 3751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of the Providers. Providers are loaded on demand only when needed. 3851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 3951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * For compatibility reasons, Providers that could not be loaded are ignored 4051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * and internally presented as the instance EMPTY_PROVIDER. However, those 4151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * objects cannot be presented to applications. Call the convert() method 4251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * to force all Providers to be loaded and to obtain a ProviderList with 4351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * invalid entries removed. All this is handled by the Security class. 4451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 4551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Note that all indices used by this class are 0-based per general Java 4651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * convention. These must be converted to the 1-based indices used by the 4751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Security class externally when needed. 4851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 4951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Instances of this class are immutable. This eliminates the need for 5051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * cloning and synchronization in consumers. The add() and remove() style 5151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * methods are static in order to avoid confusion about the immutability. 5251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 5351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @author Andreas Sterbenz 5451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @since 1.5 5551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 5651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebskipublic final class ProviderList { 5751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 5851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski final static sun.security.util.Debug debug = 5951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski sun.security.util.Debug.getInstance("jca", "ProviderList"); 6051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final static ProviderConfig[] PC0 = new ProviderConfig[0]; 6251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final static Provider[] P0 = new Provider[0]; 6451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // constant for an ProviderList with no elements 6651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static final ProviderList EMPTY = new ProviderList(PC0, true); 6751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 6851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // dummy provider object to use during initialization 6951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // used to avoid explicit null checks in various places 7051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private static final Provider EMPTY_PROVIDER = 7151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski new Provider("##Empty##", 1.0d, "initialization in progress") { 7251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // override getService() to return null slightly faster 7351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Service getService(String type, String algorithm) { 7451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 7551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 7651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski }; 7751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 7851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // construct a ProviderList from the security properties 7951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // (static provider configuration in the java.security file) 8051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski static ProviderList fromSecurityProperties() { 8151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // doPrivileged() because of Security.getProperty() 8251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return AccessController.doPrivileged( 8351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski new PrivilegedAction<ProviderList>() { 8451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public ProviderList run() { 8551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new ProviderList(); 8651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 8751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski }); 8851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 8951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 9051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static ProviderList add(ProviderList providerList, Provider p) { 9151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return insertAt(providerList, p, -1); 9251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 9351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 9451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static ProviderList insertAt(ProviderList providerList, Provider p, 9551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int position) { 9651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (providerList.getProvider(p.getName()) != null) { 9751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return providerList; 9851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 9951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski List<ProviderConfig> list = new ArrayList<> 10051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski (Arrays.asList(providerList.configs)); 10151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int n = list.size(); 10251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((position < 0) || (position > n)) { 10351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski position = n; 10451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 10551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski list.add(position, new ProviderConfig(p)); 10651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new ProviderList(list.toArray(PC0), true); 10751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 10851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 10951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static ProviderList remove(ProviderList providerList, String name) { 11051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // make sure provider exists 11151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (providerList.getProvider(name) == null) { 11251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return providerList; 11351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 11451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // copy all except matching to new list 11551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ProviderConfig[] configs = new ProviderConfig[providerList.size() - 1]; 11651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int j = 0; 11751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (ProviderConfig config : providerList.configs) { 11851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (config.getProvider().getName().equals(name) == false) { 11951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski configs[j++] = config; 12051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 12151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 12251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new ProviderList(configs, true); 12351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 12451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 12551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Create a new ProviderList from the specified Providers. 12651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // This method is for use by SunJSSE. 12751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public static ProviderList newList(Provider ... providers) { 12851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ProviderConfig[] configs = new ProviderConfig[providers.length]; 12951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < providers.length; i++) { 13051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski configs[i] = new ProviderConfig(providers[i]); 13151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 13251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new ProviderList(configs, true); 13351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 13451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 13551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // configuration of the providers 13651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final ProviderConfig[] configs; 13751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 13851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // flag indicating whether all configs have been loaded successfully 13951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private volatile boolean allLoaded; 14051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 14151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // List returned by providers() 14251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final List<Provider> userList = new AbstractList<Provider>() { 14351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int size() { 14451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return configs.length; 14551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Provider get(int index) { 14751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return getProvider(index); 14851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 14951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski }; 15051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 15151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 15251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Create a new ProviderList from an array of configs 15351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 15451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private ProviderList(ProviderConfig[] configs, boolean allLoaded) { 15551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.configs = configs; 15651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.allLoaded = allLoaded; 15751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 15851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 15951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 16051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return a new ProviderList parsed from the java.security Properties. 16151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 16251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private ProviderList() { 16351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski List<ProviderConfig> configList = new ArrayList<>(); 16451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 1; true; i++) { 16551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String entry = Security.getProperty("security.provider." + i); 16651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (entry == null) { 16751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 16851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 16951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski entry = entry.trim(); 17051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (entry.length() == 0) { 17151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski System.err.println("invalid entry for " + 17251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski "security.provider." + i); 17351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 17451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 17551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int k = entry.indexOf(' '); 17651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ProviderConfig config; 17751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (k == -1) { 17851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski config = new ProviderConfig(entry); 17951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 18051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String className = entry.substring(0, k); 18151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski String argument = entry.substring(k + 1).trim(); 18251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski config = new ProviderConfig(className, argument); 18351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 18451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 18551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // Get rid of duplicate providers. 18651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (configList.contains(config) == false) { 18751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski configList.add(config); 18851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 18951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski configs = configList.toArray(PC0); 19151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (debug != null) { 19251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski debug.println("provider configuration: " + configList); 19351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 19551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 19651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 19751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Construct a special ProviderList for JAR verification. It consists 19851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of the providers specified via jarClassNames, which must be on the 19951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * bootclasspath and cannot be in signed JAR files. This is to avoid 20051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * possible recursion and deadlock during verification. 20151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 20251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ProviderList getJarList(String[] jarClassNames) { 20351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski List<ProviderConfig> newConfigs = new ArrayList<>(); 20451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (String className : jarClassNames) { 20551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ProviderConfig newConfig = new ProviderConfig(className); 20651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (ProviderConfig config : configs) { 20751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // if the equivalent object is present in this provider list, 20851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // use the old object rather than the new object. 20951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // this ensures that when the provider is loaded in the 21051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // new thread local list, it will also become available 21151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // in this provider list 21251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (config.equals(newConfig)) { 21351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski newConfig = config; 21451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski break; 21551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 21651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 21751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski newConfigs.add(newConfig); 21851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 21951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ProviderConfig[] configArray = newConfigs.toArray(PC0); 22051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new ProviderList(configArray, false); 22151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 22251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 22351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int size() { 22451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return configs.length; 22551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 22651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 22751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 22851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return the Provider at the specified index. Returns EMPTY_PROVIDER 22951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * if the provider could not be loaded at this time. 23051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 23151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Provider getProvider(int index) { 23251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Provider p = configs[index].getProvider(); 23351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (p != null) ? p : EMPTY_PROVIDER; 23451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 23551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 23651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 23751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return an unmodifiable List of all Providers in this List. The 23851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * individual Providers are loaded on demand. Elements that could not 23951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * be initialized are replaced with EMPTY_PROVIDER. 24051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 24151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public List<Provider> providers() { 24251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return userList; 24351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 24551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private ProviderConfig getProviderConfig(String name) { 24651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int index = getIndex(name); 24751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (index != -1) ? configs[index] : null; 24851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 24951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 25051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // return the Provider with the specified name or null 25151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Provider getProvider(String name) { 25251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ProviderConfig config = getProviderConfig(name); 25351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (config == null) ? null : config.getProvider(); 25451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 25551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 25651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 25751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return the index at which the provider with the specified name is 25851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * installed or -1 if it is not present in this ProviderList. 25951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 26051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int getIndex(String name) { 26151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < configs.length; i++) { 26251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Provider p = getProvider(i); 26351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (p.getName().equals(name)) { 26451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return i; 26551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 26651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 26751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return -1; 26851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 26951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 27051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // attempt to load all Providers not already loaded 27151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private int loadAll() { 27251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (allLoaded) { 27351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return configs.length; 27451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 27551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (debug != null) { 27651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski debug.println("Loading all providers"); 27751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski new Exception("Call trace").printStackTrace(); 27851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 27951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int n = 0; 28051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < configs.length; i++) { 28151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Provider p = configs[i].getProvider(); 28251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (p != null) { 28351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski n++; 28451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 28551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 28651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (n == configs.length) { 28751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski allLoaded = true; 28851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 28951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return n; 29051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 29151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 29251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 29351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Try to load all Providers and return the ProviderList. If one or 29451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * more Providers could not be loaded, a new ProviderList with those 29551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * entries removed is returned. Otherwise, the method returns this. 29651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 29751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ProviderList removeInvalid() { 29851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int n = loadAll(); 29951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (n == configs.length) { 30051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return this; 30151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 30251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ProviderConfig[] newConfigs = new ProviderConfig[n]; 30351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0, j = 0; i < configs.length; i++) { 30451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ProviderConfig config = configs[i]; 30551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (config.isLoaded()) { 30651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski newConfigs[j++] = config; 30751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 30851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 30951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new ProviderList(newConfigs, true); 31051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 31151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 31251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // return the providers as an array 31351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Provider[] toArray() { 31451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return providers().toArray(P0); 31551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 31651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 31751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // return a String representation of this ProviderList 31851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public String toString() { 31951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return Arrays.asList(configs).toString(); 32051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 32151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 32251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 32351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return a Service describing an implementation of the specified 32451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * algorithm from the Provider with the highest precedence that 32551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * supports that algorithm. Return null if no Provider supports this 32651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * algorithm. 32751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 32851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Service getService(String type, String name) { 32951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (int i = 0; i < configs.length; i++) { 33051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Provider p = getProvider(i); 33151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Service s = p.getService(type, name); 33251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (s != null) { 33351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return s; 33451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 33551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 33651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 33751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 33851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 33951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 34051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Return a List containing all the Services describing implementations 34151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * of the specified algorithms in precedence order. If no implementation 34251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * exists, this method returns an empty List. 34351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 34451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The elements of this list are determined lazily on demand. 34551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * 34651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * The List returned is NOT thread safe. 34751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 34851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public List<Service> getServices(String type, String algorithm) { 34951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new ServiceList(type, algorithm); 35051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 35151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 35251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 35351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * This method exists for compatibility with JCE only. It will be removed 35451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * once JCE has been changed to use the replacement method. 35551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * @deprecated use getServices(List<ServiceId>) instead 35651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 35751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski @Deprecated 35851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public List<Service> getServices(String type, List<String> algorithms) { 35951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski List<ServiceId> ids = new ArrayList<>(); 36051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (String alg : algorithms) { 36151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ids.add(new ServiceId(type, alg)); 36251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 36351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return getServices(ids); 36451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 36551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 36651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public List<Service> getServices(List<ServiceId> ids) { 36751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new ServiceList(ids); 36851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 36951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 37051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski /** 37151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Inner class for a List of Services. Custom List implementation in 37251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * order to delay Provider initialization and lookup. 37351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski * Not thread safe. 37451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski */ 37551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final class ServiceList extends AbstractList<Service> { 37651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 37751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // type and algorithm for simple lookup 37851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // avoid allocating/traversing the ServiceId list for these lookups 37951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final String type; 38051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final String algorithm; 38151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 38251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // list of ids for parallel lookup 38351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // if ids is non-null, type and algorithm are null 38451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private final List<ServiceId> ids; 38551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 38651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // first service we have found 38751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // it is stored in a separate variable so that we can avoid 38851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // allocating the services list if we do not need the second service. 38951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // this is the case if we don't failover (failovers are typically rare) 39051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Service firstService; 39151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 39251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // list of the services we have found so far 39351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private List<Service> services; 39451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 39551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // index into config[] of the next provider we need to query 39651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private int providerIndex; 39751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 39851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ServiceList(String type, String algorithm) { 39951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.type = type; 40051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.algorithm = algorithm; 40151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.ids = null; 40251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 40351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 40451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski ServiceList(List<ServiceId> ids) { 40551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.type = null; 40651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.algorithm = null; 40751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski this.ids = ids; 40851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 40951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 41051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private void addService(Service s) { 41151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (firstService == null) { 41251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski firstService = s; 41351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 41451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (services == null) { 41551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski services = new ArrayList<Service>(4); 41651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski services.add(firstService); 41751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 41851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski services.add(s); 41951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 42051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 42151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 42251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski private Service tryGet(int index) { 42351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (true) { 42451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if ((index == 0) && (firstService != null)) { 42551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return firstService; 42651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else if ((services != null) && (services.size() > index)) { 42751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return services.get(index); 42851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 42951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (providerIndex >= configs.length) { 43051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return null; 43151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 43251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // check all algorithms in this provider before moving on 43351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Provider p = getProvider(providerIndex++); 43451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (type != null) { 43551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // simple lookup 43651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Service s = p.getService(type, algorithm); 43751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (s != null) { 43851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski addService(s); 43951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 44051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 44151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // parallel lookup 44251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski for (ServiceId id : ids) { 44351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Service s = p.getService(id.type, id.algorithm); 44451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (s != null) { 44551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski addService(s); 44651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 44751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 44851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 44951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 45051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 45151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 45251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Service get(int index) { 45351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Service s = tryGet(index); 45451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (s == null) { 45551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new IndexOutOfBoundsException(); 45651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 45751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return s; 45851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 45951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 46051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public int size() { 46151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int n; 46251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (services != null) { 46351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski n = services.size(); 46451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } else { 46551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski n = (firstService != null) ? 1 : 0; 46651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 46751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski while (tryGet(n) != null) { 46851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski n++; 46951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 47051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return n; 47151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 47251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 47351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // override isEmpty() and iterator() to not call size() 47451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski // this avoids loading + checking all Providers 47551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 47651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean isEmpty() { 47751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return (tryGet(0) == null); 47851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 47951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 48051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Iterator<Service> iterator() { 48151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return new Iterator<Service>() { 48251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski int index; 48351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 48451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public boolean hasNext() { 48551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return tryGet(index) != null; 48651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 48751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 48851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public Service next() { 48951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski Service s = tryGet(index); 49051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski if (s == null) { 49151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new NoSuchElementException(); 49251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 49351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski index++; 49451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski return s; 49551b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 49651b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 49751b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski public void remove() { 49851b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski throw new UnsupportedOperationException(); 49951b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 50051b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski }; 50151b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 50251b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski } 50351b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski 50451b1b6997fd3f980076b8081f7f1165ccc2a4008Piotr Jastrzebski} 505