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
26package sun.security.jca;
27
28import java.util.*;
29
30import java.security.*;
31import 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 */
56public 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}