alvinalexander.com | career | drupal | java | mac | mysql | perl | scala | uml | unix  

Java example source code file (IndexedCollectionCertStore.java)

This example Java source code file (IndexedCollectionCertStore.java) is included in the alvinalexander.com "Java Source Code Warehouse" project. The intent of this project is to help you "Learn Java by Example" TM.

Learn more about this Java project at its project page.

Java - Java tags/keywords

arraylist, collection, hashmap, hashset, invalidalgorithmparameterexception, list, object, override, security, suppresswarnings, util, x500principal, x509certificate, x509certselector, x509crl, x509crlselector

The IndexedCollectionCertStore.java Java example source code

/*
 * Copyright (c) 2002, 2012, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.security.provider.certpath;

import java.util.*;

import java.security.InvalidAlgorithmParameterException;
import java.security.cert.*;

import javax.security.auth.x500.X500Principal;

/**
 * A <code>CertStore that retrieves Certificates and
 * <code>CRLs from a Collection.
 * <p>
 * This implementation is functionally equivalent to CollectionCertStore
 * with two differences:
 * <ol>
 * <li>Upon construction, the elements in the specified Collection are
 * partially indexed. X509Certificates are indexed by subject, X509CRLs
 * by issuer, non-X509 Certificates and CRLs are copied without indexing,
 * other objects are ignored. This increases CertStore construction time
 * but allows significant speedups for searches which specify the indexed
 * attributes, in particular for large Collections (reduction from linear
 * time to effectively constant time). Searches for non-indexed queries
 * are as fast (or marginally faster) than for the standard
 * CollectionCertStore. Certificate subjects and CRL issuers
 * were found to be specified in most searches used internally by the
 * CertPath provider. Additional attributes could indexed if there are
 * queries that justify the effort.
 *
 * <li>Changes to the specified Collection after construction time are
 * not detected and ignored. This is because there is no way to efficiently
 * detect if a Collection has been modified, a full traversal would be
 * required. That would degrade lookup performance to linear time and
 * eliminated the benefit of indexing. We may fix this via the introduction
 * of new public APIs in the future.
 * </ol>
 * <p>
 * Before calling the {@link #engineGetCertificates engineGetCertificates} or
 * {@link #engineGetCRLs engineGetCRLs} methods, the
 * {@link #CollectionCertStore(CertStoreParameters)
 * CollectionCertStore(CertStoreParameters)} constructor is called to
 * create the <code>CertStore and establish the
 * <code>Collection from which Certificates and
 * <code>CRLs will be retrieved. If the specified
 * <code>Collection contains an object that is not a
 * <code>Certificate or CRL, that object will be
 * ignored.
 * <p>
 * <b>Concurrent Access
 * <p>
 * As described in the javadoc for <code>CertStoreSpi, the
 * <code>engineGetCertificates and engineGetCRLs methods
 * must be thread-safe. That is, multiple threads may concurrently
 * invoke these methods on a single <code>CollectionCertStore
 * object (or more than one) with no ill effects.
 * <p>
 * This is achieved by requiring that the <code>Collection passed to
 * the {@link #CollectionCertStore(CertStoreParameters)
 * CollectionCertStore(CertStoreParameters)} constructor (via the
 * <code>CollectionCertStoreParameters object) must have fail-fast
 * iterators. Simultaneous modifications to the <code>Collection can thus be
 * detected and certificate or CRL retrieval can be retried. The fact that
 * <code>Certificates and CRLs must be thread-safe is also
 * essential.
 *
 * @see java.security.cert.CertStore
 * @see CollectionCertStore
 *
 * @author Andreas Sterbenz
 */
public class IndexedCollectionCertStore extends CertStoreSpi {

    /**
     * Map X500Principal(subject) -> X509Certificate | List of X509Certificate
     */
    private Map<X500Principal, Object> certSubjects;
    /**
     * Map X500Principal(issuer) -> X509CRL | List of X509CRL
     */
    private Map<X500Principal, Object> crlIssuers;
    /**
     * Sets of non-X509 certificates and CRLs
     */
    private Set<Certificate> otherCertificates;
    private Set<CRL> otherCRLs;

    /**
     * Creates a <code>CertStore with the specified parameters.
     * For this class, the parameters object must be an instance of
     * <code>CollectionCertStoreParameters.
     *
     * @param params the algorithm parameters
     * @exception InvalidAlgorithmParameterException if params is not an
     *   instance of <code>CollectionCertStoreParameters
     */
    public IndexedCollectionCertStore(CertStoreParameters params)
            throws InvalidAlgorithmParameterException {
        super(params);
        if (!(params instanceof CollectionCertStoreParameters)) {
            throw new InvalidAlgorithmParameterException(
                "parameters must be CollectionCertStoreParameters");
        }
        Collection<?> coll = ((CollectionCertStoreParameters)params).getCollection();
        if (coll == null) {
            throw new InvalidAlgorithmParameterException
                                        ("Collection must not be null");
        }
        buildIndex(coll);
    }

    /**
     * Index the specified Collection copying all references to Certificates
     * and CRLs.
     */
    private void buildIndex(Collection<?> coll) {
        certSubjects = new HashMap<X500Principal, Object>();
        crlIssuers = new HashMap<X500Principal, Object>();
        otherCertificates = null;
        otherCRLs = null;
        for (Object obj : coll) {
            if (obj instanceof X509Certificate) {
                indexCertificate((X509Certificate)obj);
            } else if (obj instanceof X509CRL) {
                indexCRL((X509CRL)obj);
            } else if (obj instanceof Certificate) {
                if (otherCertificates == null) {
                    otherCertificates = new HashSet<Certificate>();
                }
                otherCertificates.add((Certificate)obj);
            } else if (obj instanceof CRL) {
                if (otherCRLs == null) {
                    otherCRLs = new HashSet<CRL>();
                }
                otherCRLs.add((CRL)obj);
            } else {
                // ignore
            }
        }
        if (otherCertificates == null) {
            otherCertificates = Collections.<Certificate>emptySet();
        }
        if (otherCRLs == null) {
            otherCRLs = Collections.<CRL>emptySet();
        }
    }

    /**
     * Add an X509Certificate to the index.
     */
    private void indexCertificate(X509Certificate cert) {
        X500Principal subject = cert.getSubjectX500Principal();
        Object oldEntry = certSubjects.put(subject, cert);
        if (oldEntry != null) { // assume this is unlikely
            if (oldEntry instanceof X509Certificate) {
                if (cert.equals(oldEntry)) {
                    return;
                }
                List<X509Certificate> list = new ArrayList<>(2);
                list.add(cert);
                list.add((X509Certificate)oldEntry);
                certSubjects.put(subject, list);
            } else {
                @SuppressWarnings("unchecked") // See certSubjects javadoc.
                List<X509Certificate> list = (List)oldEntry;
                if (list.contains(cert) == false) {
                    list.add(cert);
                }
                certSubjects.put(subject, list);
            }
        }
    }

    /**
     * Add an X509CRL to the index.
     */
    private void indexCRL(X509CRL crl) {
        X500Principal issuer = crl.getIssuerX500Principal();
        Object oldEntry = crlIssuers.put(issuer, crl);
        if (oldEntry != null) { // assume this is unlikely
            if (oldEntry instanceof X509CRL) {
                if (crl.equals(oldEntry)) {
                    return;
                }
                List<X509CRL> list = new ArrayList<>(2);
                list.add(crl);
                list.add((X509CRL)oldEntry);
                crlIssuers.put(issuer, list);
            } else {
                // See crlIssuers javadoc.
                @SuppressWarnings("unchecked")
                List<X509CRL> list = (List)oldEntry;
                if (list.contains(crl) == false) {
                    list.add(crl);
                }
                crlIssuers.put(issuer, list);
            }
        }
    }

    /**
     * Returns a <code>Collection of Certificates that
     * match the specified selector. If no <code>Certificates
     * match the selector, an empty <code>Collection will be returned.
     *
     * @param selector a <code>CertSelector used to select which
     *  <code>Certificates should be returned. Specify null
     *  to return all <code>Certificates.
     * @return a <code>Collection of Certificates that
     *         match the specified selector
     * @throws CertStoreException if an exception occurs
     */
    @Override
    public Collection<? extends Certificate> engineGetCertificates(CertSelector selector)
            throws CertStoreException {

        // no selector means match all
        if (selector == null) {
            Set<Certificate> matches = new HashSet<>();
            matchX509Certs(new X509CertSelector(), matches);
            matches.addAll(otherCertificates);
            return matches;
        }

        if (selector instanceof X509CertSelector == false) {
            Set<Certificate> matches = new HashSet<>();
            matchX509Certs(selector, matches);
            for (Certificate cert : otherCertificates) {
                if (selector.match(cert)) {
                    matches.add(cert);
                }
            }
            return matches;
        }

        if (certSubjects.isEmpty()) {
            return Collections.<X509Certificate>emptySet();
        }
        X509CertSelector x509Selector = (X509CertSelector)selector;
        // see if the subject is specified
        X500Principal subject;
        X509Certificate matchCert = x509Selector.getCertificate();
        if (matchCert != null) {
            subject = matchCert.getSubjectX500Principal();
        } else {
            subject = x509Selector.getSubject();
        }
        if (subject != null) {
            // yes, narrow down candidates to indexed possibilities
            Object entry = certSubjects.get(subject);
            if (entry == null) {
                return Collections.<X509Certificate>emptySet();
            }
            if (entry instanceof X509Certificate) {
                X509Certificate x509Entry = (X509Certificate)entry;
                if (x509Selector.match(x509Entry)) {
                    return Collections.singleton(x509Entry);
                } else {
                    return Collections.<X509Certificate>emptySet();
                }
            } else {
                // See certSubjects javadoc.
                @SuppressWarnings("unchecked")
                List<X509Certificate> list = (List)entry;
                Set<X509Certificate> matches = new HashSet<>(16);
                for (X509Certificate cert : list) {
                    if (x509Selector.match(cert)) {
                        matches.add(cert);
                    }
                }
                return matches;
            }
        }
        // cannot use index, iterate all
        Set<Certificate> matches = new HashSet<>(16);
        matchX509Certs(x509Selector, matches);
        return matches;
    }

    /**
     * Iterate through all the X509Certificates and add matches to the
     * collection.
     */
    private void matchX509Certs(CertSelector selector,
        Collection<Certificate> matches) {

        for (Object obj : certSubjects.values()) {
            if (obj instanceof X509Certificate) {
                X509Certificate cert = (X509Certificate)obj;
                if (selector.match(cert)) {
                    matches.add(cert);
                }
            } else {
                // See certSubjects javadoc.
                @SuppressWarnings("unchecked")
                List<X509Certificate> list = (List)obj;
                for (X509Certificate cert : list) {
                    if (selector.match(cert)) {
                        matches.add(cert);
                    }
                }
            }
        }
    }

    /**
     * Returns a <code>Collection of CRLs that
     * match the specified selector. If no <code>CRLs
     * match the selector, an empty <code>Collection will be returned.
     *
     * @param selector a <code>CRLSelector used to select which
     *  <code>CRLs should be returned. Specify null
     *  to return all <code>CRLs.
     * @return a <code>Collection of CRLs that
     *         match the specified selector
     * @throws CertStoreException if an exception occurs
     */
    @Override
    public Collection<CRL> engineGetCRLs(CRLSelector selector)
            throws CertStoreException {

        if (selector == null) {
            Set<CRL> matches = new HashSet<>();
            matchX509CRLs(new X509CRLSelector(), matches);
            matches.addAll(otherCRLs);
            return matches;
        }

        if (selector instanceof X509CRLSelector == false) {
            Set<CRL> matches = new HashSet<>();
            matchX509CRLs(selector, matches);
            for (CRL crl : otherCRLs) {
                if (selector.match(crl)) {
                    matches.add(crl);
                }
            }
            return matches;
        }

        if (crlIssuers.isEmpty()) {
            return Collections.<CRL>emptySet();
        }
        X509CRLSelector x509Selector = (X509CRLSelector)selector;
        // see if the issuer is specified
        Collection<X500Principal> issuers = x509Selector.getIssuers();
        if (issuers != null) {
            HashSet<CRL> matches = new HashSet<>(16);
            for (X500Principal issuer : issuers) {
                Object entry = crlIssuers.get(issuer);
                if (entry == null) {
                    // empty
                } else if (entry instanceof X509CRL) {
                    X509CRL crl = (X509CRL)entry;
                    if (x509Selector.match(crl)) {
                        matches.add(crl);
                    }
                } else { // List
                    // See crlIssuers javadoc.
                    @SuppressWarnings("unchecked")
                    List<X509CRL> list = (List)entry;
                    for (X509CRL crl : list) {
                        if (x509Selector.match(crl)) {
                            matches.add(crl);
                        }
                    }
                }
            }
            return matches;
        }
        // cannot use index, iterate all
        Set<CRL> matches = new HashSet<>(16);
        matchX509CRLs(x509Selector, matches);
        return matches;
    }

    /**
     * Iterate through all the X509CRLs and add matches to the
     * collection.
     */
    private void matchX509CRLs(CRLSelector selector, Collection<CRL> matches) {
        for (Object obj : crlIssuers.values()) {
            if (obj instanceof X509CRL) {
                X509CRL crl = (X509CRL)obj;
                if (selector.match(crl)) {
                    matches.add(crl);
                }
            } else {
                // See crlIssuers javadoc.
                @SuppressWarnings("unchecked")
                List<X509CRL> list = (List)obj;
                for (X509CRL crl : list) {
                    if (selector.match(crl)) {
                        matches.add(crl);
                    }
                }
            }
        }
    }

}

Other Java examples (source code examples)

Here is a short list of links related to this Java IndexedCollectionCertStore.java source code file:

... this post is sponsored by my books ...

#1 New Release!

FP Best Seller

 

new blog posts

 

Copyright 1998-2021 Alvin Alexander, alvinalexander.com
All Rights Reserved.

A percentage of advertising revenue from
pages under the /java/jwarehouse URI on this website is
paid back to open source projects.