History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/security/jca/ProviderList.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/jca/ProviderList.java+504−0
@@ -0,0 +1,504 @@
1+/*
2+ * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
5+ * This code is free software; you can redistribute it and/or modify it
6+ * under the terms of the GNU General Public License version 2 only, as
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+package sun.security.jca;
27+
28+import java.util.*;
29+
30+import java.security.*;
31+import java.security.Provider.Service;
32+
33+/**
34+ * List of Providers. Used to represent the provider preferences.
35+ *
36+ * The system starts out with a ProviderList that only has the classNames
37+ * of the Providers. Providers are loaded on demand only when needed.
38+ *
39+ * For compatibility reasons, Providers that could not be loaded are ignored
40+ * and internally presented as the instance EMPTY_PROVIDER. However, those
41+ * objects cannot be presented to applications. Call the convert() method
42+ * to force all Providers to be loaded and to obtain a ProviderList with
43+ * invalid entries removed. All this is handled by the Security class.
44+ *
45+ * Note that all indices used by this class are 0-based per general Java
46+ * convention. These must be converted to the 1-based indices used by the
47+ * Security class externally when needed.
48+ *
49+ * Instances of this class are immutable. This eliminates the need for
50+ * cloning and synchronization in consumers. The add() and remove() style
51+ * methods are static in order to avoid confusion about the immutability.
52+ *
53+ * @author Andreas Sterbenz
54+ * @since 1.5
55+ */
56+public final class ProviderList {
57+
58+ final static sun.security.util.Debug debug =
59+ sun.security.util.Debug.getInstance("jca", "ProviderList");
60+
61+ private final static ProviderConfig[] PC0 = new ProviderConfig[0];
62+
63+ private final static Provider[] P0 = new Provider[0];
64+
65+ // constant for an ProviderList with no elements
66+ static final ProviderList EMPTY = new ProviderList(PC0, true);
67+
68+ // dummy provider object to use during initialization
69+ // used to avoid explicit null checks in various places
70+ private static final Provider EMPTY_PROVIDER =
71+ new Provider("##Empty##", 1.0d, "initialization in progress") {
72+ // override getService() to return null slightly faster
73+ public Service getService(String type, String algorithm) {
74+ return null;
75+ }
76+ };
77+
78+ // construct a ProviderList from the security properties
79+ // (static provider configuration in the java.security file)
80+ static ProviderList fromSecurityProperties() {
81+ // doPrivileged() because of Security.getProperty()
82+ return AccessController.doPrivileged(
83+ new PrivilegedAction<ProviderList>() {
84+ public ProviderList run() {
85+ return new ProviderList();
86+ }
87+ });
88+ }
89+
90+ public static ProviderList add(ProviderList providerList, Provider p) {
91+ return insertAt(providerList, p, -1);
92+ }
93+
94+ public static ProviderList insertAt(ProviderList providerList, Provider p,
95+ int position) {
96+ if (providerList.getProvider(p.getName()) != null) {
97+ return providerList;
98+ }
99+ List<ProviderConfig> list = new ArrayList<>
100+ (Arrays.asList(providerList.configs));
101+ int n = list.size();
102+ if ((position < 0) || (position > n)) {
103+ position = n;
104+ }
105+ list.add(position, new ProviderConfig(p));
106+ return new ProviderList(list.toArray(PC0), true);
107+ }
108+
109+ public static ProviderList remove(ProviderList providerList, String name) {
110+ // make sure provider exists
111+ if (providerList.getProvider(name) == null) {
112+ return providerList;
113+ }
114+ // copy all except matching to new list
115+ ProviderConfig[] configs = new ProviderConfig[providerList.size() - 1];
116+ int j = 0;
117+ for (ProviderConfig config : providerList.configs) {
118+ if (config.getProvider().getName().equals(name) == false) {
119+ configs[j++] = config;
120+ }
121+ }
122+ return new ProviderList(configs, true);
123+ }
124+
125+ // Create a new ProviderList from the specified Providers.
126+ // This method is for use by SunJSSE.
127+ public static ProviderList newList(Provider ... providers) {
128+ ProviderConfig[] configs = new ProviderConfig[providers.length];
129+ for (int i = 0; i < providers.length; i++) {
130+ configs[i] = new ProviderConfig(providers[i]);
131+ }
132+ return new ProviderList(configs, true);
133+ }
134+
135+ // configuration of the providers
136+ private final ProviderConfig[] configs;
137+
138+ // flag indicating whether all configs have been loaded successfully
139+ private volatile boolean allLoaded;
140+
141+ // List returned by providers()
142+ private final List<Provider> userList = new AbstractList<Provider>() {
143+ public int size() {
144+ return configs.length;
145+ }
146+ public Provider get(int index) {
147+ return getProvider(index);
148+ }
149+ };
150+
151+ /**
152+ * Create a new ProviderList from an array of configs
153+ */
154+ private ProviderList(ProviderConfig[] configs, boolean allLoaded) {
155+ this.configs = configs;
156+ this.allLoaded = allLoaded;
157+ }
158+
159+ /**
160+ * Return a new ProviderList parsed from the java.security Properties.
161+ */
162+ private ProviderList() {
163+ List<ProviderConfig> configList = new ArrayList<>();
164+ for (int i = 1; true; i++) {
165+ String entry = Security.getProperty("security.provider." + i);
166+ if (entry == null) {
167+ break;
168+ }
169+ entry = entry.trim();
170+ if (entry.length() == 0) {
171+ System.err.println("invalid entry for " +
172+ "security.provider." + i);
173+ break;
174+ }
175+ int k = entry.indexOf(' ');
176+ ProviderConfig config;
177+ if (k == -1) {
178+ config = new ProviderConfig(entry);
179+ } else {
180+ String className = entry.substring(0, k);
181+ String argument = entry.substring(k + 1).trim();
182+ config = new ProviderConfig(className, argument);
183+ }
184+
185+ // Get rid of duplicate providers.
186+ if (configList.contains(config) == false) {
187+ configList.add(config);
188+ }
189+ }
190+ configs = configList.toArray(PC0);
191+ if (debug != null) {
192+ debug.println("provider configuration: " + configList);
193+ }
194+ }
195+
196+ /**
197+ * Construct a special ProviderList for JAR verification. It consists
198+ * of the providers specified via jarClassNames, which must be on the
199+ * bootclasspath and cannot be in signed JAR files. This is to avoid
200+ * possible recursion and deadlock during verification.
201+ */
202+ ProviderList getJarList(String[] jarClassNames) {
203+ List<ProviderConfig> newConfigs = new ArrayList<>();
204+ for (String className : jarClassNames) {
205+ ProviderConfig newConfig = new ProviderConfig(className);
206+ for (ProviderConfig config : configs) {
207+ // if the equivalent object is present in this provider list,
208+ // use the old object rather than the new object.
209+ // this ensures that when the provider is loaded in the
210+ // new thread local list, it will also become available
211+ // in this provider list
212+ if (config.equals(newConfig)) {
213+ newConfig = config;
214+ break;
215+ }
216+ }
217+ newConfigs.add(newConfig);
218+ }
219+ ProviderConfig[] configArray = newConfigs.toArray(PC0);
220+ return new ProviderList(configArray, false);
221+ }
222+
223+ public int size() {
224+ return configs.length;
225+ }
226+
227+ /**
228+ * Return the Provider at the specified index. Returns EMPTY_PROVIDER
229+ * if the provider could not be loaded at this time.
230+ */
231+ Provider getProvider(int index) {
232+ Provider p = configs[index].getProvider();
233+ return (p != null) ? p : EMPTY_PROVIDER;
234+ }
235+
236+ /**
237+ * Return an unmodifiable List of all Providers in this List. The
238+ * individual Providers are loaded on demand. Elements that could not
239+ * be initialized are replaced with EMPTY_PROVIDER.
240+ */
241+ public List<Provider> providers() {
242+ return userList;
243+ }
244+
245+ private ProviderConfig getProviderConfig(String name) {
246+ int index = getIndex(name);
247+ return (index != -1) ? configs[index] : null;
248+ }
249+
250+ // return the Provider with the specified name or null
251+ public Provider getProvider(String name) {
252+ ProviderConfig config = getProviderConfig(name);
253+ return (config == null) ? null : config.getProvider();
254+ }
255+
256+ /**
257+ * Return the index at which the provider with the specified name is
258+ * installed or -1 if it is not present in this ProviderList.
259+ */
260+ public int getIndex(String name) {
261+ for (int i = 0; i < configs.length; i++) {
262+ Provider p = getProvider(i);
263+ if (p.getName().equals(name)) {
264+ return i;
265+ }
266+ }
267+ return -1;
268+ }
269+
270+ // attempt to load all Providers not already loaded
271+ private int loadAll() {
272+ if (allLoaded) {
273+ return configs.length;
274+ }
275+ if (debug != null) {
276+ debug.println("Loading all providers");
277+ new Exception("Call trace").printStackTrace();
278+ }
279+ int n = 0;
280+ for (int i = 0; i < configs.length; i++) {
281+ Provider p = configs[i].getProvider();
282+ if (p != null) {
283+ n++;
284+ }
285+ }
286+ if (n == configs.length) {
287+ allLoaded = true;
288+ }
289+ return n;
290+ }
291+
292+ /**
293+ * Try to load all Providers and return the ProviderList. If one or
294+ * more Providers could not be loaded, a new ProviderList with those
295+ * entries removed is returned. Otherwise, the method returns this.
296+ */
297+ ProviderList removeInvalid() {
298+ int n = loadAll();
299+ if (n == configs.length) {
300+ return this;
301+ }
302+ ProviderConfig[] newConfigs = new ProviderConfig[n];
303+ for (int i = 0, j = 0; i < configs.length; i++) {
304+ ProviderConfig config = configs[i];
305+ if (config.isLoaded()) {
306+ newConfigs[j++] = config;
307+ }
308+ }
309+ return new ProviderList(newConfigs, true);
310+ }
311+
312+ // return the providers as an array
313+ public Provider[] toArray() {
314+ return providers().toArray(P0);
315+ }
316+
317+ // return a String representation of this ProviderList
318+ public String toString() {
319+ return Arrays.asList(configs).toString();
320+ }
321+
322+ /**
323+ * Return a Service describing an implementation of the specified
324+ * algorithm from the Provider with the highest precedence that
325+ * supports that algorithm. Return null if no Provider supports this
326+ * algorithm.
327+ */
328+ public Service getService(String type, String name) {
329+ for (int i = 0; i < configs.length; i++) {
330+ Provider p = getProvider(i);
331+ Service s = p.getService(type, name);
332+ if (s != null) {
333+ return s;
334+ }
335+ }
336+ return null;
337+ }
338+
339+ /**
340+ * Return a List containing all the Services describing implementations
341+ * of the specified algorithms in precedence order. If no implementation
342+ * exists, this method returns an empty List.
343+ *
344+ * The elements of this list are determined lazily on demand.
345+ *
346+ * The List returned is NOT thread safe.
347+ */
348+ public List<Service> getServices(String type, String algorithm) {
349+ return new ServiceList(type, algorithm);
350+ }
351+
352+ /**
353+ * This method exists for compatibility with JCE only. It will be removed
354+ * once JCE has been changed to use the replacement method.
355+ * @deprecated use getServices(List<ServiceId>) instead
356+ */
357+ @Deprecated
358+ public List<Service> getServices(String type, List<String> algorithms) {
359+ List<ServiceId> ids = new ArrayList<>();
360+ for (String alg : algorithms) {
361+ ids.add(new ServiceId(type, alg));
362+ }
363+ return getServices(ids);
364+ }
365+
366+ public List<Service> getServices(List<ServiceId> ids) {
367+ return new ServiceList(ids);
368+ }
369+
370+ /**
371+ * Inner class for a List of Services. Custom List implementation in
372+ * order to delay Provider initialization and lookup.
373+ * Not thread safe.
374+ */
375+ private final class ServiceList extends AbstractList<Service> {
376+
377+ // type and algorithm for simple lookup
378+ // avoid allocating/traversing the ServiceId list for these lookups
379+ private final String type;
380+ private final String algorithm;
381+
382+ // list of ids for parallel lookup
383+ // if ids is non-null, type and algorithm are null
384+ private final List<ServiceId> ids;
385+
386+ // first service we have found
387+ // it is stored in a separate variable so that we can avoid
388+ // allocating the services list if we do not need the second service.
389+ // this is the case if we don't failover (failovers are typically rare)
390+ private Service firstService;
391+
392+ // list of the services we have found so far
393+ private List<Service> services;
394+
395+ // index into config[] of the next provider we need to query
396+ private int providerIndex;
397+
398+ ServiceList(String type, String algorithm) {
399+ this.type = type;
400+ this.algorithm = algorithm;
401+ this.ids = null;
402+ }
403+
404+ ServiceList(List<ServiceId> ids) {
405+ this.type = null;
406+ this.algorithm = null;
407+ this.ids = ids;
408+ }
409+
410+ private void addService(Service s) {
411+ if (firstService == null) {
412+ firstService = s;
413+ } else {
414+ if (services == null) {
415+ services = new ArrayList<Service>(4);
416+ services.add(firstService);
417+ }
418+ services.add(s);
419+ }
420+ }
421+
422+ private Service tryGet(int index) {
423+ while (true) {
424+ if ((index == 0) && (firstService != null)) {
425+ return firstService;
426+ } else if ((services != null) && (services.size() > index)) {
427+ return services.get(index);
428+ }
429+ if (providerIndex >= configs.length) {
430+ return null;
431+ }
432+ // check all algorithms in this provider before moving on
433+ Provider p = getProvider(providerIndex++);
434+ if (type != null) {
435+ // simple lookup
436+ Service s = p.getService(type, algorithm);
437+ if (s != null) {
438+ addService(s);
439+ }
440+ } else {
441+ // parallel lookup
442+ for (ServiceId id : ids) {
443+ Service s = p.getService(id.type, id.algorithm);
444+ if (s != null) {
445+ addService(s);
446+ }
447+ }
448+ }
449+ }
450+ }
451+
452+ public Service get(int index) {
453+ Service s = tryGet(index);
454+ if (s == null) {
455+ throw new IndexOutOfBoundsException();
456+ }
457+ return s;
458+ }
459+
460+ public int size() {
461+ int n;
462+ if (services != null) {
463+ n = services.size();
464+ } else {
465+ n = (firstService != null) ? 1 : 0;
466+ }
467+ while (tryGet(n) != null) {
468+ n++;
469+ }
470+ return n;
471+ }
472+
473+ // override isEmpty() and iterator() to not call size()
474+ // this avoids loading + checking all Providers
475+
476+ public boolean isEmpty() {
477+ return (tryGet(0) == null);
478+ }
479+
480+ public Iterator<Service> iterator() {
481+ return new Iterator<Service>() {
482+ int index;
483+
484+ public boolean hasNext() {
485+ return tryGet(index) != null;
486+ }
487+
488+ public Service next() {
489+ Service s = tryGet(index);
490+ if (s == null) {
491+ throw new NoSuchElementException();
492+ }
493+ index++;
494+ return s;
495+ }
496+
497+ public void remove() {
498+ throw new UnsupportedOperationException();
499+ }
500+ };
501+ }
502+ }
503+
504+}