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/provider/certpath/IndexedCollectionCertStore.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/provider/certpath/IndexedCollectionCertStore.java+411−0
@@ -0,0 +1,411 @@
1/*
2 * Copyright (c) 2002, 2006, 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.provider.certpath;
27
28import java.util.*;
29
30import java.security.InvalidAlgorithmParameterException;
31import java.security.cert.*;
32
33import javax.security.auth.x500.X500Principal;
34
35/**
36 * A <code>CertStore</code> that retrieves <code>Certificates</code> and
37 * <code>CRL</code>s from a <code>Collection</code>.
38 * <p>
39 * This implementation is functionally equivalent to CollectionCertStore
40 * with two differences:
41 * <ol>
42 * <li>Upon construction, the elements in the specified Collection are
43 * partially indexed. X509Certificates are indexed by subject, X509CRLs
44 * by issuer, non-X509 Certificates and CRLs are copied without indexing,
45 * other objects are ignored. This increases CertStore construction time
46 * but allows significant speedups for searches which specify the indexed
47 * attributes, in particular for large Collections (reduction from linear
48 * time to effectively constant time). Searches for non-indexed queries
49 * are as fast (or marginally faster) than for the standard
50 * CollectionCertStore. Certificate subjects and CRL issuers
51 * were found to be specified in most searches used internally by the
52 * CertPath provider. Additional attributes could indexed if there are
53 * queries that justify the effort.
54 *
55 * <li>Changes to the specified Collection after construction time are
56 * not detected and ignored. This is because there is no way to efficiently
57 * detect if a Collection has been modified, a full traversal would be
58 * required. That would degrade lookup performance to linear time and
59 * eliminated the benefit of indexing. We may fix this via the introduction
60 * of new public APIs in the future.
61 * </ol>
62 * <p>
63 * Before calling the {@link #engineGetCertificates engineGetCertificates} or
64 * {@link #engineGetCRLs engineGetCRLs} methods, the
65 * {@link #CollectionCertStore(CertStoreParameters)
66 * CollectionCertStore(CertStoreParameters)} constructor is called to
67 * create the <code>CertStore</code> and establish the
68 * <code>Collection</code> from which <code>Certificate</code>s and
69 * <code>CRL</code>s will be retrieved. If the specified
70 * <code>Collection</code> contains an object that is not a
71 * <code>Certificate</code> or <code>CRL</code>, that object will be
72 * ignored.
73 * <p>
74 * <b>Concurrent Access</b>
75 * <p>
76 * As described in the javadoc for <code>CertStoreSpi</code>, the
77 * <code>engineGetCertificates</code> and <code>engineGetCRLs</code> methods
78 * must be thread-safe. That is, multiple threads may concurrently
79 * invoke these methods on a single <code>CollectionCertStore</code>
80 * object (or more than one) with no ill effects.
81 * <p>
82 * This is achieved by requiring that the <code>Collection</code> passed to
83 * the {@link #CollectionCertStore(CertStoreParameters)
84 * CollectionCertStore(CertStoreParameters)} constructor (via the
85 * <code>CollectionCertStoreParameters</code> object) must have fail-fast
86 * iterators. Simultaneous modifications to the <code>Collection</code> can thus be
87 * detected and certificate or CRL retrieval can be retried. The fact that
88 * <code>Certificate</code>s and <code>CRL</code>s must be thread-safe is also
89 * essential.
90 *
91 * @see java.security.cert.CertStore
92 * @see CollectionCertStore
93 *
94 * @author Andreas Sterbenz
95 */
96public class IndexedCollectionCertStore extends CertStoreSpi {
97
98 /**
99 * Map X500Principal(subject) -> X509Certificate | List of X509Certificate
100 */
101 private Map<X500Principal, Object> certSubjects;
102 /**
103 * Map X500Principal(issuer) -> X509CRL | List of X509CRL
104 */
105 private Map<X500Principal, Object> crlIssuers;
106 /**
107 * Sets of non-X509 certificates and CRLs
108 */
109 private Set<Certificate> otherCertificates;
110 private Set<CRL> otherCRLs;
111
112 /**
113 * Creates a <code>CertStore</code> with the specified parameters.
114 * For this class, the parameters object must be an instance of
115 * <code>CollectionCertStoreParameters</code>.
116 *
117 * @param params the algorithm parameters
118 * @exception InvalidAlgorithmParameterException if params is not an
119 * instance of <code>CollectionCertStoreParameters</code>
120 */
121 public IndexedCollectionCertStore(CertStoreParameters params)
122 throws InvalidAlgorithmParameterException {
123 super(params);
124 if (!(params instanceof CollectionCertStoreParameters)) {
125 throw new InvalidAlgorithmParameterException(
126 "parameters must be CollectionCertStoreParameters");
127 }
128 Collection<?> coll = ((CollectionCertStoreParameters)params).getCollection();
129 if (coll == null) {
130 throw new InvalidAlgorithmParameterException
131 ("Collection must not be null");
132 }
133 buildIndex(coll);
134 }
135
136 /**
137 * Index the specified Collection copying all references to Certificates
138 * and CRLs.
139 */
140 private void buildIndex(Collection<?> coll) {
141 certSubjects = new HashMap<X500Principal, Object>();
142 crlIssuers = new HashMap<X500Principal, Object>();
143 otherCertificates = null;
144 otherCRLs = null;
145 for (Object obj : coll) {
146 if (obj instanceof X509Certificate) {
147 indexCertificate((X509Certificate)obj);
148 } else if (obj instanceof X509CRL) {
149 indexCRL((X509CRL)obj);
150 } else if (obj instanceof Certificate) {
151 if (otherCertificates == null) {
152 otherCertificates = new HashSet<Certificate>();
153 }
154 otherCertificates.add((Certificate)obj);
155 } else if (obj instanceof CRL) {
156 if (otherCRLs == null) {
157 otherCRLs = new HashSet<CRL>();
158 }
159 otherCRLs.add((CRL)obj);
160 } else {
161 // ignore
162 }
163 }
164 if (otherCertificates == null) {
165 otherCertificates = Collections.<Certificate>emptySet();
166 }
167 if (otherCRLs == null) {
168 otherCRLs = Collections.<CRL>emptySet();
169 }
170 }
171
172 /**
173 * Add an X509Certificate to the index.
174 */
175 private void indexCertificate(X509Certificate cert) {
176 X500Principal subject = cert.getSubjectX500Principal();
177 Object oldEntry = certSubjects.put(subject, cert);
178 if (oldEntry != null) { // assume this is unlikely
179 if (oldEntry instanceof X509Certificate) {
180 if (cert.equals(oldEntry)) {
181 return;
182 }
183 List<X509Certificate> list = new ArrayList<X509Certificate>(2);
184 list.add(cert);
185 list.add((X509Certificate)oldEntry);
186 certSubjects.put(subject, list);
187 } else {
188 List<X509Certificate> list = (List<X509Certificate>)oldEntry;
189 if (list.contains(cert) == false) {
190 list.add(cert);
191 }
192 certSubjects.put(subject, list);
193 }
194 }
195 }
196
197 /**
198 * Add an X509CRL to the index.
199 */
200 private void indexCRL(X509CRL crl) {
201 X500Principal issuer = crl.getIssuerX500Principal();
202 Object oldEntry = crlIssuers.put(issuer, crl);
203 if (oldEntry != null) { // assume this is unlikely
204 if (oldEntry instanceof X509CRL) {
205 if (crl.equals(oldEntry)) {
206 return;
207 }
208 List<X509CRL> list = new ArrayList<X509CRL>(2);
209 list.add(crl);
210 list.add((X509CRL)oldEntry);
211 crlIssuers.put(issuer, list);
212 } else {
213 List<X509CRL> list = (List<X509CRL>)oldEntry;
214 if (list.contains(crl) == false) {
215 list.add(crl);
216 }
217 crlIssuers.put(issuer, list);
218 }
219 }
220 }
221
222 /**
223 * Returns a <code>Collection</code> of <code>Certificate</code>s that
224 * match the specified selector. If no <code>Certificate</code>s
225 * match the selector, an empty <code>Collection</code> will be returned.
226 *
227 * @param selector a <code>CertSelector</code> used to select which
228 * <code>Certificate</code>s should be returned. Specify <code>null</code>
229 * to return all <code>Certificate</code>s.
230 * @return a <code>Collection</code> of <code>Certificate</code>s that
231 * match the specified selector
232 * @throws CertStoreException if an exception occurs
233 */
234 public Collection<? extends Certificate> engineGetCertificates(CertSelector selector)
235 throws CertStoreException {
236
237 // no selector means match all
238 if (selector == null) {
239 Set<Certificate> matches = new HashSet<Certificate>();
240 matchX509Certs(new X509CertSelector(), matches);
241 matches.addAll(otherCertificates);
242 return matches;
243 }
244
245 if (selector instanceof X509CertSelector == false) {
246 Set<Certificate> matches = new HashSet<Certificate>();
247 matchX509Certs(selector, matches);
248 for (Certificate cert : otherCertificates) {
249 if (selector.match(cert)) {
250 matches.add(cert);
251 }
252 }
253 return matches;
254 }
255
256 if (certSubjects.isEmpty()) {
257 return Collections.<X509Certificate>emptySet();
258 }
259 X509CertSelector x509Selector = (X509CertSelector)selector;
260 // see if the subject is specified
261 X500Principal subject;
262 X509Certificate matchCert = x509Selector.getCertificate();
263 if (matchCert != null) {
264 subject = matchCert.getSubjectX500Principal();
265 } else {
266 subject = x509Selector.getSubject();
267 }
268 if (subject != null) {
269 // yes, narrow down candidates to indexed possibilities
270 Object entry = certSubjects.get(subject);
271 if (entry == null) {
272 return Collections.<X509Certificate>emptySet();
273 }
274 if (entry instanceof X509Certificate) {
275 X509Certificate x509Entry = (X509Certificate)entry;
276 if (x509Selector.match(x509Entry)) {
277 return Collections.singleton(x509Entry);
278 } else {
279 return Collections.<X509Certificate>emptySet();
280 }
281 } else {
282 List<X509Certificate> list = (List<X509Certificate>)entry;
283 Set<X509Certificate> matches = new HashSet<X509Certificate>(16);
284 for (X509Certificate cert : list) {
285 if (x509Selector.match(cert)) {
286 matches.add(cert);
287 }
288 }
289 return matches;
290 }
291 }
292 // cannot use index, iterate all
293 Set<Certificate> matches = new HashSet<Certificate>(16);
294 matchX509Certs(x509Selector, matches);
295 return matches;
296 }
297
298 /**
299 * Iterate through all the X509Certificates and add matches to the
300 * collection.
301 */
302 private void matchX509Certs(CertSelector selector,
303 Collection<Certificate> matches) {
304
305 for (Object obj : certSubjects.values()) {
306 if (obj instanceof X509Certificate) {
307 X509Certificate cert = (X509Certificate)obj;
308 if (selector.match(cert)) {
309 matches.add(cert);
310 }
311 } else {
312 List<X509Certificate> list = (List<X509Certificate>)obj;
313 for (X509Certificate cert : list) {
314 if (selector.match(cert)) {
315 matches.add(cert);
316 }
317 }
318 }
319 }
320 }
321
322 /**
323 * Returns a <code>Collection</code> of <code>CRL</code>s that
324 * match the specified selector. If no <code>CRL</code>s
325 * match the selector, an empty <code>Collection</code> will be returned.
326 *
327 * @param selector a <code>CRLSelector</code> used to select which
328 * <code>CRL</code>s should be returned. Specify <code>null</code>
329 * to return all <code>CRL</code>s.
330 * @return a <code>Collection</code> of <code>CRL</code>s that
331 * match the specified selector
332 * @throws CertStoreException if an exception occurs
333 */
334 public Collection<CRL> engineGetCRLs(CRLSelector selector)
335 throws CertStoreException {
336
337 if (selector == null) {
338 Set<CRL> matches = new HashSet<CRL>();
339 matchX509CRLs(new X509CRLSelector(), matches);
340 matches.addAll(otherCRLs);
341 return matches;
342 }
343
344 if (selector instanceof X509CRLSelector == false) {
345 Set<CRL> matches = new HashSet<CRL>();
346 matchX509CRLs(selector, matches);
347 for (CRL crl : otherCRLs) {
348 if (selector.match(crl)) {
349 matches.add(crl);
350 }
351 }
352 return matches;
353 }
354
355 if (crlIssuers.isEmpty()) {
356 return Collections.<CRL>emptySet();
357 }
358 X509CRLSelector x509Selector = (X509CRLSelector)selector;
359 // see if the issuer is specified
360 Collection<X500Principal> issuers = x509Selector.getIssuers();
361 if (issuers != null) {
362 HashSet<CRL> matches = new HashSet<CRL>(16);
363 for (X500Principal issuer : issuers) {
364 Object entry = crlIssuers.get(issuer);
365 if (entry == null) {
366 // empty
367 } else if (entry instanceof X509CRL) {
368 X509CRL crl = (X509CRL)entry;
369 if (x509Selector.match(crl)) {
370 matches.add(crl);
371 }
372 } else { // List
373 List<X509CRL> list = (List<X509CRL>)entry;
374 for (X509CRL crl : list) {
375 if (x509Selector.match(crl)) {
376 matches.add(crl);
377 }
378 }
379 }
380 }
381 return matches;
382 }
383 // cannot use index, iterate all
384 Set<CRL> matches = new HashSet<CRL>(16);
385 matchX509CRLs(x509Selector, matches);
386 return matches;
387 }
388
389 /**
390 * Iterate through all the X509CRLs and add matches to the
391 * collection.
392 */
393 private void matchX509CRLs(CRLSelector selector, Collection<CRL> matches) {
394 for (Object obj : crlIssuers.values()) {
395 if (obj instanceof X509CRL) {
396 X509CRL crl = (X509CRL)obj;
397 if (selector.match(crl)) {
398 matches.add(crl);
399 }
400 } else {
401 List<X509CRL> list = (List<X509CRL>)obj;
402 for (X509CRL crl : list) {
403 if (selector.match(crl)) {
404 matches.add(crl);
405 }
406 }
407 }
408 }
409 }
410
411}