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+
26+package sun.security.provider.certpath;
27+
28+import java.util.*;
29+
30+import java.security.InvalidAlgorithmParameterException;
31+import java.security.cert.*;
32+
33+import 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+ */
96+public 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+}