KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > java > security > KeyStore


1 /*
2  * @(#)KeyStore.java 1.42 04/06/28
3  *
4  * Copyright 2004 Sun Microsystems, Inc. All rights reserved.
5  * SUN PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
6  */

7
8 package java.security;
9
10 import java.io.*;
11 import java.security.cert.Certificate JavaDoc;
12 import java.security.cert.X509Certificate JavaDoc;
13 import java.security.cert.CertificateException JavaDoc;
14 import java.util.*;
15 import javax.crypto.SecretKey;
16
17 import javax.security.auth.callback.*;
18
19 /**
20  * This class represents a storage facility for cryptographic
21  * keys and certificates.
22  *
23  * <p> A <code>KeyStore</code> manages different types of entries.
24  * Each type of entry implements the <code>KeyStore.Entry</code> interface.
25  * Three basic <code>KeyStore.Entry</code> implementations are provided:
26  *
27  * <ul>
28  * <li><b>KeyStore.PrivateKeyEntry</b>
29  * <p> This type of entry holds a cryptographic <code>PrivateKey</code>,
30  * which is optionally stored in a protected format to prevent
31  * unauthorized access. It is also accompanied by a certificate chain
32  * for the corresponding public key.
33  *
34  * <p> Private keys and certificate chains are used by a given entity for
35  * self-authentication. Applications for this authentication include software
36  * distribution organizations which sign JAR files as part of releasing
37  * and/or licensing software.
38  *
39  * <li><b>KeyStore.SecretKeyEntry</b>
40  * <p> This type of entry holds a cryptographic <code>SecretKey</code>,
41  * which is optionally stored in a protected format to prevent
42  * unauthorized access.
43  *
44  * <li><b>KeyStore.TrustedCertificateEntry</b>
45  * <p> This type of entry contains a single public key <code>Certificate</code>
46  * belonging to another party. It is called a <i>trusted certificate</i>
47  * because the keystore owner trusts that the public key in the certificate
48  * indeed belongs to the identity identified by the <i>subject</i> (owner)
49  * of the certificate.
50  *
51  * <p>This type of entry can be used to authenticate other parties.
52  * </ul>
53  *
54  * <p> Each entry in a keystore is identified by an "alias" string. In the
55  * case of private keys and their associated certificate chains, these strings
56  * distinguish among the different ways in which the entity may authenticate
57  * itself. For example, the entity may authenticate itself using different
58  * certificate authorities, or using different public key algorithms.
59  *
60  * <p> Whether keystores are persistent, and the mechanisms used by the
61  * keystore if it is persistent, are not specified here. This allows
62  * use of a variety of techniques for protecting sensitive (e.g., private or
63  * secret) keys. Smart cards or other integrated cryptographic engines
64  * (SafeKeyper) are one option, and simpler mechanisms such as files may also
65  * be used (in a variety of formats).
66  *
67  * <p> Typical ways to request a KeyStore object include
68  * relying on the default type and providing a specific keystore type.
69  *
70  * <ul>
71  * <li>To rely on the default type:
72  * <pre>
73  * KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
74  * </pre>
75  * The system will return a keystore implementation for the default type.
76  * <p>
77  *
78  * <li>To provide a specific keystore type:
79  * <pre>
80  * KeyStore ks = KeyStore.getInstance("JKS");
81  * </pre>
82  * The system will return the most preferred implementation of the
83  * specified keystore type available in the environment. <p>
84  * </ul>
85  *
86  * <p> Before a keystore can be accessed, it must be
87  * {@link #load(java.io.InputStream, char[]) loaded}.
88  * <pre>
89  * KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
90  *
91  * // get user password and file input stream
92  * char[] password = getPassword();
93  * java.io.FileInputStream fis =
94  * new java.io.FileInputStream("keyStoreName");
95  * ks.load(fis, password);
96  * fis.close();
97  * </pre>
98  *
99  * To create an empty keystore using the above <code>load</code> method,
100  * pass <code>null</code> as the <code>InputStream</code> argument.
101  *
102  * <p> Once the keystore has been loaded, it is possible
103  * to read existing entries from the keystore, or to write new entries
104  * into the keystore:
105  * <pre>
106  * // get my private key
107  * KeyStore.PrivateKeyEntry pkEntry = (KeyStore.PrivateKeyEntry)
108  * ks.getEntry("privateKeyAlias", password);
109  * PrivateKey myPrivateKey = pkEntry.getPrivateKey();
110  *
111  * // save my secret key
112  * javax.crypto.SecretKey mySecretKey;
113  * KeyStore.SecretKeyEntry skEntry =
114  * new KeyStore.SecretKeyEntry(mySecretKey);
115  * ks.setEntry("secretKeyAlias", skEntry, password);
116  *
117  * // store away the keystore
118  * java.io.FileOutputStream fos =
119  * new java.io.FileOutputStream("newKeyStoreName");
120  * ks.store(fos, password);
121  * fos.close();
122  * </pre>
123  *
124  * Note that although the same password may be used to
125  * load the keystore, to protect the private key entry,
126  * to protect the secret key entry, and to store the keystore
127  * (as is shown in the sample code above),
128  * different passwords or other protection parameters
129  * may also be used.
130  *
131  * @author Jan Luehe
132  *
133  * @version 1.42, 06/28/04
134  *
135  * @see java.security.PrivateKey
136  * @see javax.crypto.SecretKey
137  * @see java.security.cert.Certificate
138  *
139  * @since 1.2
140  */

141
142 public class KeyStore {
143
144     /*
145      * Constant to lookup in the Security properties file to determine
146      * the default keystore type.
147      * In the Security properties file, the default keystore type is given as:
148      * <pre>
149      * keystore.type=jks
150      * </pre>
151      */

152     private static final String JavaDoc KEYSTORE_TYPE = "keystore.type";
153
154     // The keystore type
155
private String JavaDoc type;
156
157     // The provider
158
private Provider JavaDoc provider;
159
160     // The provider implementation
161
private KeyStoreSpi JavaDoc keyStoreSpi;
162
163     // Has this keystore been initialized (loaded)?
164
private boolean initialized = false;
165
166     /**
167      * A marker interface for <code>KeyStore</code>
168      * {@link #load(KeyStore.LoadStoreParameter) load}
169      * and
170      * {@link #store(KeyStore.LoadStoreParameter) store}
171      * parameters.
172      *
173      * @since 1.5
174      */

175     public static interface LoadStoreParameter {
176     /**
177      * Gets the parameter used to protect keystore data.
178      *
179      * @return the parameter used to protect keystore data, or null
180      */

181     public ProtectionParameter getProtectionParameter();
182     }
183
184     /**
185      * A marker interface for keystore protection parameters.
186      *
187      * <p> The information stored in a <code>ProtectionParameter</code>
188      * object protects the contents of a keystore.
189      * For example, protection parameters may be used to check
190      * the integrity of keystore data, or to protect the
191      * confidentiality of sensitive keystore data
192      * (such as a <code>PrivateKey</code>).
193      *
194      * @since 1.5
195      */

196     public static interface ProtectionParameter { }
197
198     /**
199      * A password-based implementation of <code>ProtectionParameter</code>.
200      *
201      * @since 1.5
202      */

203     public static class PasswordProtection implements
204         ProtectionParameter, javax.security.auth.Destroyable JavaDoc {
205
206     private final char[] password;
207     private volatile boolean destroyed = false;
208
209     /**
210      * Creates a password parameter.
211      *
212      * <p> The specified <code>password</code> is cloned before it is stored
213      * in the new <code>PasswordProtection</code> object.
214      *
215      * @param password the password, which may be <code>null</code>
216      */

217     public PasswordProtection(char[] password) {
218         this.password = (password == null) ?
219                 null : (char[])password.clone();
220     }
221
222     /**
223      * Gets the password.
224      *
225      * <p>Note that this method returns a reference to the password.
226      * If a clone of the array is created it is the caller's
227      * responsibility to zero out the password information
228      * after it is no longer needed.
229      *
230      * @see #destroy()
231      * @return the password, which may be <code>null</code>
232      * @exception IllegalStateException if the password has
233      * been cleared (destroyed)
234      */

235     public synchronized char[] getPassword() {
236         if (destroyed) {
237         throw new IllegalStateException JavaDoc("password has been cleared");
238         }
239         return password;
240     }
241
242     /**
243      * Clears the password.
244      *
245      * @exception DestroyFailedException if this method was unable
246      * to clear the password
247      */

248     public synchronized void destroy()
249         throws javax.security.auth.DestroyFailedException JavaDoc {
250         destroyed = true;
251         if (password != null) {
252         Arrays.fill(password, ' ');
253         }
254     }
255
256     /**
257      * Determines if password has been cleared.
258      *
259      * @return true if the password has been cleared, false otherwise
260      */

261     public synchronized boolean isDestroyed() {
262         return destroyed;
263     }
264     }
265
266     /**
267      * A ProtectionParameter encapsulating a CallbackHandler.
268      *
269      * @since 1.5
270      */

271     public static class CallbackHandlerProtection
272         implements ProtectionParameter {
273         
274     private final CallbackHandler handler;
275     
276     /**
277      * Constructs a new CallbackHandlerProtection from a
278      * CallbackHandler.
279      *
280      * @param handler the CallbackHandler
281      * @exception NullPointerException if handler is null
282      */

283     public CallbackHandlerProtection(CallbackHandler handler) {
284         if (handler == null) {
285         throw new NullPointerException JavaDoc("handler must not be null");
286         }
287         this.handler = handler;
288     }
289     
290     /**
291      * Returns the CallbackHandler.
292      *
293      * @return the CallbackHandler.
294      */

295     public CallbackHandler getCallbackHandler() {
296         return handler;
297     }
298     
299     }
300
301     /**
302      * A marker interface for <code>KeyStore</code> entry types.
303      *
304      * @since 1.5
305      */

306     public static interface Entry { }
307
308     /**
309      * A <code>KeyStore</code> entry that holds a <code>PrivateKey</code>
310      * and corresponding certificate chain.
311      *
312      * @since 1.5
313      */

314     public static final class PrivateKeyEntry implements Entry {
315
316     private final PrivateKey JavaDoc privKey;
317     private final Certificate JavaDoc[] chain;
318
319     /**
320      * Constructs a <code>PrivateKeyEntry</code> with a
321      * <code>PrivateKey</code> and corresponding certificate chain.
322      *
323      * <p> The specified <code>chain</code> is cloned before it is stored
324      * in the new <code>PrivateKeyEntry</code> object.
325      *
326      * @param privateKey the <code>PrivateKey</code>
327      * @param chain an array of <code>Certificate</code>s
328      * representing the certificate chain.
329      * The chain must be ordered and contain a
330      * <code>Certificate</code> at index 0
331      * corresponding to the private key.
332      *
333      * @exception NullPointerException if
334      * <code>privateKey</code> or <code>chain</code>
335      * is <code>null</code>
336      * @exception IllegalArgumentException if the specified chain has a
337      * length of 0, if the specified chain does not contain
338      * <code>Certificate</code>s of the same type,
339      * or if the <code>PrivateKey</code> algorithm
340      * does not match the algorithm of the <code>PublicKey</code>
341      * in the end entity <code>Certificate</code> (at index 0)
342      */

343     public PrivateKeyEntry(PrivateKey JavaDoc privateKey, Certificate JavaDoc[] chain) {
344         if (privateKey == null || chain == null) {
345         throw new NullPointerException JavaDoc("invalid null input");
346         }
347         if (chain.length == 0) {
348         throw new IllegalArgumentException JavaDoc
349                 ("invalid zero-length input chain");
350         }
351
352         Certificate JavaDoc[] clonedChain = (Certificate JavaDoc[])chain.clone();
353         String JavaDoc certType = clonedChain[0].getType();
354         for (int i = 1; i < clonedChain.length; i++) {
355         if (!certType.equals(clonedChain[i].getType())) {
356             throw new IllegalArgumentException JavaDoc
357                 ("chain does not contain certificates " +
358                 "of the same type");
359         }
360         }
361         if (!privateKey.getAlgorithm().equals
362             (clonedChain[0].getPublicKey().getAlgorithm())) {
363         throw new IllegalArgumentException JavaDoc
364                 ("private key algorithm does not match " +
365                 "algorithm of public key in end entity " +
366                 "certificate (at index 0)");
367         }
368         this.privKey = privateKey;
369
370         if (clonedChain[0] instanceof X509Certificate JavaDoc &&
371         !(clonedChain instanceof X509Certificate JavaDoc[])) {
372
373         this.chain = new X509Certificate JavaDoc[clonedChain.length];
374         System.arraycopy(clonedChain, 0,
375                 this.chain, 0, clonedChain.length);
376         } else {
377         this.chain = clonedChain;
378         }
379     }
380
381     /**
382      * Gets the <code>PrivateKey</code> from this entry.
383      *
384      * @return the <code>PrivateKey</code> from this entry
385      */

386     public PrivateKey JavaDoc getPrivateKey() {
387         return privKey;
388     }
389
390     /**
391      * Gets the <code>Certificate</code> chain from this entry.
392      *
393      * <p> The stored chain is cloned before being returned.
394      *
395      * @return an array of <code>Certificate</code>s corresponding
396      * to the certificate chain for the public key.
397      * If the certificates are of type X.509,
398      * the runtime type of the returned array is
399      * <code>X509Certificate[]</code>.
400      */

401     public Certificate JavaDoc[] getCertificateChain() {
402         return (Certificate JavaDoc[])chain.clone();
403     }
404
405     /**
406      * Gets the end entity <code>Certificate</code>
407      * from the certificate chain in this entry.
408      *
409      * @return the end entity <code>Certificate</code> (at index 0)
410      * from the certificate chain in this entry.
411      * If the certificate is of type X.509,
412      * the runtime type of the returned certificate is
413      * <code>X509Certificate</code>.
414      */

415     public Certificate JavaDoc getCertificate() {
416         return chain[0];
417     }
418
419     /**
420      * Returns a string representation of this PrivateKeyEntry.
421      * @return a string representation of this PrivateKeyEntry.
422      */

423     public String JavaDoc toString() {
424         StringBuilder JavaDoc sb = new StringBuilder JavaDoc();
425         sb.append("Private key entry and certificate chain with "
426         + chain.length + " elements:\r\n");
427         for (Certificate JavaDoc cert : chain) {
428         sb.append(cert);
429         sb.append("\r\n");
430         }
431         return sb.toString();
432     }
433
434     }
435
436     /**
437      * A <code>KeyStore</code> entry that holds a <code>SecretKey</code>.
438      *
439      * @since 1.5
440      */

441     public static final class SecretKeyEntry implements Entry {
442
443     private final SecretKey sKey;
444
445     /**
446      * Constructs a <code>SecretKeyEntry</code> with a
447      * <code>SecretKey</code>.
448      *
449      * @param secretKey the <code>SecretKey</code>
450      *
451      * @exception NullPointerException if <code>secretKey</code>
452      * is <code>null</code>
453      */

454     public SecretKeyEntry(SecretKey secretKey) {
455         if (secretKey == null) {
456         throw new NullPointerException JavaDoc("invalid null input");
457         }
458         this.sKey = secretKey;
459     }
460
461     /**
462      * Gets the <code>SecretKey</code> from this entry.
463      *
464      * @return the <code>SecretKey</code> from this entry
465      */

466     public SecretKey getSecretKey() {
467         return sKey;
468     }
469     
470     /**
471      * Returns a string representation of this SecretKeyEntry.
472      * @return a string representation of this SecretKeyEntry.
473      */

474     public String JavaDoc toString() {
475         return "Secret key entry with algorithm " + sKey.getAlgorithm();
476     }
477     }
478
479     /**
480      * A <code>KeyStore</code> entry that holds a trusted
481      * <code>Certificate</code>.
482      *
483      * @since 1.5
484      */

485     public static final class TrustedCertificateEntry implements Entry {
486
487     private final Certificate JavaDoc cert;
488
489     /**
490      * Constructs a <code>TrustedCertificateEntry</code> with a
491      * trusted <code>Certificate</code>.
492      *
493      * @param trustedCert the trusted <code>Certificate</code>
494      *
495      * @exception NullPointerException if
496      * <code>trustedCert</code> is <code>null</code>
497      */

498     public TrustedCertificateEntry(Certificate JavaDoc trustedCert) {
499         if (trustedCert == null) {
500         throw new NullPointerException JavaDoc("invalid null input");
501         }
502         this.cert = trustedCert;
503     }
504
505     /**
506      * Gets the trusted <code>Certficate</code> from this entry.
507      *
508      * @return the trusted <code>Certificate</code> from this entry
509      */

510     public Certificate JavaDoc getTrustedCertificate() {
511         return cert;
512     }
513     
514     /**
515      * Returns a string representation of this TrustedCertificateEntry.
516      * @return a string representation of this TrustedCertificateEntry.
517      */

518     public String JavaDoc toString() {
519         return "Trusted certificate entry:\r\n" + cert.toString();
520     }
521     }
522
523     /**
524      * Creates a KeyStore object of the given type, and encapsulates the given
525      * provider implementation (SPI object) in it.
526      *
527      * @param keyStoreSpi the provider implementation.
528      * @param provider the provider.
529      * @param type the keystore type.
530      */

531     protected KeyStore(KeyStoreSpi JavaDoc keyStoreSpi, Provider JavaDoc provider, String JavaDoc type)
532     {
533     this.keyStoreSpi = keyStoreSpi;
534     this.provider = provider;
535     this.type = type;
536     }
537
538     /**
539      * Generates a keystore object of the given type.
540      *
541      * <p>If the default provider package provides a keystore implementation
542      * of the given type, an instance of <code>KeyStore</code> containing that
543      * implementation is returned. If the requested keystore type is not
544      * available in the default package, other packages are searched.
545      *
546      * @param type the type of keystore.
547      * See Appendix A in the <a HREF=
548      * "../../../guide/security/CryptoSpec.html#AppA">
549      * Java Cryptography Architecture API Specification &amp; Reference </a>
550      * for information about standard keystore types.
551      *
552      * @return a keystore object of the specified type.
553      *
554      * @exception KeyStoreException if the requested keystore type is
555      * not available in the default provider package or any of the other
556      * provider packages that were searched.
557      */

558     public static KeyStore JavaDoc getInstance(String JavaDoc type)
559     throws KeyStoreException JavaDoc
560     {
561     try {
562         Object JavaDoc[] objs = Security.getImpl(type, "KeyStore", (String JavaDoc)null);
563         return new KeyStore JavaDoc((KeyStoreSpi JavaDoc)objs[0], (Provider JavaDoc)objs[1], type);
564     } catch (NoSuchAlgorithmException JavaDoc nsae) {
565         throw new KeyStoreException JavaDoc(type + " not found");
566     } catch (NoSuchProviderException JavaDoc nspe) {
567         throw new KeyStoreException JavaDoc(type + " not found");
568     }
569     }
570
571     /**
572      * Generates a keystore object for the specified keystore
573      * type from the specified provider.
574      *
575      * @param type the type of keystore.
576      * See Appendix A in the <a HREF=
577      * "../../../guide/security/CryptoSpec.html#AppA">
578      * Java Cryptography Architecture API Specification &amp; Reference </a>
579      * for information about standard keystore types.
580      *
581      * @param provider the name of the provider.
582      *
583      * @return a keystore object of the specified type, as
584      * supplied by the specified provider.
585      *
586      * @exception KeyStoreException if the requested keystore type is not
587      * available from the provider.
588      *
589      * @exception NoSuchProviderException if the provider has not been
590      * configured.
591      *
592      * @exception IllegalArgumentException if the provider name is null
593      * or empty.
594      *
595      * @see Provider
596      */

597     public static KeyStore JavaDoc getInstance(String JavaDoc type, String JavaDoc provider)
598     throws KeyStoreException JavaDoc, NoSuchProviderException JavaDoc
599     {
600     if (provider == null || provider.length() == 0)
601         throw new IllegalArgumentException JavaDoc("missing provider");
602     try {
603         Object JavaDoc[] objs = Security.getImpl(type, "KeyStore", provider);
604         return new KeyStore JavaDoc((KeyStoreSpi JavaDoc)objs[0], (Provider JavaDoc)objs[1], type);
605     } catch (NoSuchAlgorithmException JavaDoc nsae) {
606         throw new KeyStoreException JavaDoc(type + " not found");
607     }
608     }
609
610     /**
611      * Generates a keystore object for the specified keystore
612      * type from the specified provider. Note: the <code>provider</code>
613      * doesn't have to be registered.
614      *
615      * @param type the type of keystore.
616      * See Appendix A in the <a HREF=
617      * "../../../guide/security/CryptoSpec.html#AppA">
618      * Java Cryptography Architecture API Specification &amp; Reference </a>
619      * for information about standard keystore types.
620      *
621      * @param provider the provider.
622      *
623      * @return a keystore object of the specified type, as
624      * supplied by the specified provider.
625      *
626      * @exception KeyStoreException if the requested keystore type is not
627      * available from the provider.
628      *
629      * @exception IllegalArgumentException if the <code>provider</code> is
630      * null.
631      *
632      * @see Provider
633      *
634      * @since 1.4
635      */

636     public static KeyStore JavaDoc getInstance(String JavaDoc type, Provider JavaDoc provider)
637     throws KeyStoreException JavaDoc
638     {
639     if (provider == null)
640         throw new IllegalArgumentException JavaDoc("missing provider");
641     try {
642         Object JavaDoc[] objs = Security.getImpl(type, "KeyStore", provider);
643         return new KeyStore JavaDoc((KeyStoreSpi JavaDoc)objs[0], (Provider JavaDoc)objs[1], type);
644     } catch (NoSuchAlgorithmException JavaDoc nsae) {
645         throw new KeyStoreException JavaDoc(type + " not found");
646     }
647     }
648
649     /**
650      * Returns the default keystore type as specified in the Java security
651      * properties file, or the string
652      * &quot;jks&quot; (acronym for &quot;Java keystore&quot;)
653      * if no such property exists.
654      * The Java security properties file is located in the file named
655      * &lt;JAVA_HOME&gt;/lib/security/java.security, where &lt;JAVA_HOME&gt;
656      * refers to the directory where the JDK was installed.
657      *
658      * <p>The default keystore type can be used by applications that do not
659      * want to use a hard-coded keystore type when calling one of the
660      * <code>getInstance</code> methods, and want to provide a default keystore
661      * type in case a user does not specify its own.
662      *
663      * <p>The default keystore type can be changed by setting the value of the
664      * "keystore.type" security property (in the Java security properties
665      * file) to the desired keystore type.
666      *
667      * @return the default keystore type as specified in the
668      * Java security properties file, or the string &quot;jks&quot;
669      * if no such property exists.
670      */

671     public final static String JavaDoc getDefaultType() {
672     String JavaDoc kstype;
673     kstype = (String JavaDoc)AccessController.doPrivileged(new PrivilegedAction JavaDoc() {
674         public Object JavaDoc run() {
675         return Security.getProperty(KEYSTORE_TYPE);
676         }
677     });
678     if (kstype == null) {
679         kstype = "jks";
680     }
681     return kstype;
682     }
683
684     /**
685      * Returns the provider of this keystore.
686      *
687      * @return the provider of this keystore.
688      */

689     public final Provider JavaDoc getProvider()
690     {
691     return this.provider;
692     }
693
694     /**
695      * Returns the type of this keystore.
696      *
697      * @return the type of this keystore.
698      */

699     public final String JavaDoc getType()
700     {
701     return this.type;
702     }
703
704     /**
705      * Returns the key associated with the given alias, using the given
706      * password to recover it. The key must have been associated with
707      * the alias by a call to <code>setKeyEntry</code>,
708      * or by a call to <code>setEntry</code> with a
709      * <code>PrivateKeyEntry</code> or <code>SecretKeyEntry</code>.
710      *
711      * @param alias the alias name
712      * @param password the password for recovering the key
713      *
714      * @return the requested key, or null if the given alias does not exist
715      * or does not identify a key-related entry.
716      *
717      * @exception KeyStoreException if the keystore has not been initialized
718      * (loaded).
719      * @exception NoSuchAlgorithmException if the algorithm for recovering the
720      * key cannot be found
721      * @exception UnrecoverableKeyException if the key cannot be recovered
722      * (e.g., the given password is wrong).
723      */

724     public final Key JavaDoc getKey(String JavaDoc alias, char[] password)
725     throws KeyStoreException JavaDoc, NoSuchAlgorithmException JavaDoc,
726         UnrecoverableKeyException JavaDoc
727     {
728     if (!initialized) {
729         throw new KeyStoreException JavaDoc("Uninitialized keystore");
730     }
731     return keyStoreSpi.engineGetKey(alias, password);
732     }
733
734     /**
735      * Returns the certificate chain associated with the given alias.
736      * The certificate chain must have been associated with the alias
737      * by a call to <code>setKeyEntry</code>,
738      * or by a call to <code>setEntry</code> with a
739      * <code>PrivateKeyEntry</code>.
740      *
741      * @param alias the alias name
742      *
743      * @return the certificate chain (ordered with the user's certificate first
744      * and the root certificate authority last), or null if the given alias
745      * does not exist or does not contain a certificate chain
746      *
747      * @exception KeyStoreException if the keystore has not been initialized
748      * (loaded).
749      */

750     public final Certificate JavaDoc[] getCertificateChain(String JavaDoc alias)
751     throws KeyStoreException JavaDoc
752     {
753     if (!initialized) {
754         throw new KeyStoreException JavaDoc("Uninitialized keystore");
755     }
756     return keyStoreSpi.engineGetCertificateChain(alias);
757     }
758
759     /**
760      * Returns the certificate associated with the given alias.
761      *
762      * <p> If the given alias name identifies an entry
763      * created by a call to <code>setCertificateEntry</code>,
764      * or created by a call to <code>setEntry</code> with a
765      * <code>TrustedCertificateEntry</code>,
766      * then the trusted certificate contained in that entry is returned.
767      *
768      * <p> If the given alias name identifies an entry
769      * created by a call to <code>setKeyEntry</code>,
770      * or created by a call to <code>setEntry</code> with a
771      * <code>PrivateKeyEntry</code>,
772      * then the first element of the certificate chain in that entry
773      * is returned.
774      *
775      * @param alias the alias name
776      *
777      * @return the certificate, or null if the given alias does not exist or
778      * does not contain a certificate.
779      *
780      * @exception KeyStoreException if the keystore has not been initialized
781      * (loaded).
782      */

783     public final Certificate JavaDoc getCertificate(String JavaDoc alias)
784     throws KeyStoreException JavaDoc
785     {
786     if (!initialized) {
787         throw new KeyStoreException JavaDoc("Uninitialized keystore");
788     }
789     return keyStoreSpi.engineGetCertificate(alias);
790     }
791
792     /**
793      * Returns the creation date of the entry identified by the given alias.
794      *
795      * @param alias the alias name
796      *
797      * @return the creation date of this entry, or null if the given alias does
798      * not exist
799      *
800      * @exception KeyStoreException if the keystore has not been initialized
801      * (loaded).
802      */

803     public final Date getCreationDate(String JavaDoc alias)
804     throws KeyStoreException JavaDoc
805     {
806     if (!initialized) {
807         throw new KeyStoreException JavaDoc("Uninitialized keystore");
808     }
809     return keyStoreSpi.engineGetCreationDate(alias);
810     }
811
812     /**
813      * Assigns the given key to the given alias, protecting it with the given
814      * password.
815      *
816      * <p>If the given key is of type <code>java.security.PrivateKey</code>,
817      * it must be accompanied by a certificate chain certifying the
818      * corresponding public key.
819      *
820      * <p>If the given alias already exists, the keystore information
821      * associated with it is overridden by the given key (and possibly
822      * certificate chain).
823      *
824      * @param alias the alias name
825      * @param key the key to be associated with the alias
826      * @param password the password to protect the key
827      * @param chain the certificate chain for the corresponding public
828      * key (only required if the given key is of type
829      * <code>java.security.PrivateKey</code>).
830      *
831      * @exception KeyStoreException if the keystore has not been initialized
832      * (loaded), the given key cannot be protected, or this operation fails
833      * for some other reason
834      */

835     public final void setKeyEntry(String JavaDoc alias, Key JavaDoc key, char[] password,
836                   Certificate JavaDoc[] chain)
837     throws KeyStoreException JavaDoc
838     {
839     if (!initialized) {
840         throw new KeyStoreException JavaDoc("Uninitialized keystore");
841     }
842     if ((key instanceof PrivateKey JavaDoc) &&
843         (chain == null || chain.length == 0)) {
844         throw new IllegalArgumentException JavaDoc("Private key must be "
845                            + "accompanied by certificate "
846                            + "chain");
847     }
848     keyStoreSpi.engineSetKeyEntry(alias, key, password, chain);
849     }
850
851     /**
852      * Assigns the given key (that has already been protected) to the given
853      * alias.
854      *
855      * <p>If the protected key is of type
856      * <code>java.security.PrivateKey</code>, it must be accompanied by a
857      * certificate chain certifying the corresponding public key. If the
858      * underlying keystore implementation is of type <code>jks</code>,
859      * <code>key</code> must be encoded as an
860      * <code>EncryptedPrivateKeyInfo</code> as defined in the PKCS #8 standard.
861      *
862      * <p>If the given alias already exists, the keystore information
863      * associated with it is overridden by the given key (and possibly
864      * certificate chain).
865      *
866      * @param alias the alias name
867      * @param key the key (in protected format) to be associated with the alias
868      * @param chain the certificate chain for the corresponding public
869      * key (only useful if the protected key is of type
870      * <code>java.security.PrivateKey</code>).
871      *
872      * @exception KeyStoreException if the keystore has not been initialized
873      * (loaded), or if this operation fails for some other reason.
874      */

875     public final void setKeyEntry(String JavaDoc alias, byte[] key,
876                   Certificate JavaDoc[] chain)
877     throws KeyStoreException JavaDoc
878     {
879     if (!initialized) {
880         throw new KeyStoreException JavaDoc("Uninitialized keystore");
881     }
882     keyStoreSpi.engineSetKeyEntry(alias, key, chain);
883     }
884
885     /**
886      * Assigns the given trusted certificate to the given alias.
887      *
888      * <p> If the given alias identifies an existing entry
889      * created by a call to <code>setCertificateEntry</code>,
890      * or created by a call to <code>setEntry</code> with a
891      * <code>TrustedCertificateEntry</code>,
892      * the trusted certificate in the existing entry
893      * is overridden by the given certificate.
894      *
895      * @param alias the alias name
896      * @param cert the certificate
897      *
898      * @exception KeyStoreException if the keystore has not been initialized,
899      * or the given alias already exists and does not identify an
900      * entry containing a trusted certificate,
901      * or this operation fails for some other reason.
902      */

903     public final void setCertificateEntry(String JavaDoc alias, Certificate JavaDoc cert)
904     throws KeyStoreException JavaDoc
905     {
906     if (!initialized) {
907         throw new KeyStoreException JavaDoc("Uninitialized keystore");
908     }
909     keyStoreSpi.engineSetCertificateEntry(alias, cert);
910     }
911
912     /**
913      * Deletes the entry identified by the given alias from this keystore.
914      *
915      * @param alias the alias name
916      *
917      * @exception KeyStoreException if the keystore has not been initialized,
918      * or if the entry cannot be removed.
919      */

920     public final void deleteEntry(String JavaDoc alias)
921     throws KeyStoreException JavaDoc
922     {
923     if (!initialized) {
924         throw new KeyStoreException JavaDoc("Uninitialized keystore");
925     }
926     keyStoreSpi.engineDeleteEntry(alias);
927     }
928
929     /**
930      * Lists all the alias names of this keystore.
931      *
932      * @return enumeration of the alias names
933      *
934      * @exception KeyStoreException if the keystore has not been initialized
935      * (loaded).
936      */

937     public final Enumeration<String JavaDoc> aliases()
938     throws KeyStoreException JavaDoc
939     {
940     if (!initialized) {
941         throw new KeyStoreException JavaDoc("Uninitialized keystore");
942     }
943     return keyStoreSpi.engineAliases();
944     }
945
946     /**
947      * Checks if the given alias exists in this keystore.
948      *
949      * @param alias the alias name
950      *
951      * @return true if the alias exists, false otherwise
952      *
953      * @exception KeyStoreException if the keystore has not been initialized
954      * (loaded).
955      */

956     public final boolean containsAlias(String JavaDoc alias)
957     throws KeyStoreException JavaDoc
958     {
959     if (!initialized) {
960         throw new KeyStoreException JavaDoc("Uninitialized keystore");
961     }
962     return keyStoreSpi.engineContainsAlias(alias);
963     }
964
965     /**
966      * Retrieves the number of entries in this keystore.
967      *
968      * @return the number of entries in this keystore
969      *
970      * @exception KeyStoreException if the keystore has not been initialized
971      * (loaded).
972      */

973     public final int size()
974     throws KeyStoreException JavaDoc
975     {
976     if (!initialized) {
977         throw new KeyStoreException JavaDoc("Uninitialized keystore");
978     }
979     return keyStoreSpi.engineSize();
980     }
981
982     /**
983      * Returns true if the entry identified by the given alias
984      * was created by a call to <code>setKeyEntry</code>,
985      * or created by a call to <code>setEntry</code> with a
986      * <code>PrivateKeyEntry</code> or a <code>SecretKeyEntry</code>.
987      *
988      * @param alias the alias for the keystore entry to be checked
989      *
990      * @return true if the entry identified by the given alias is a
991      * key-related entry, false otherwise.
992      *
993      * @exception KeyStoreException if the keystore has not been initialized
994      * (loaded).
995      */

996     public final boolean isKeyEntry(String JavaDoc alias)
997     throws KeyStoreException JavaDoc
998     {
999     if (!initialized) {
1000        throw new KeyStoreException JavaDoc("Uninitialized keystore");
1001    }
1002    return keyStoreSpi.engineIsKeyEntry(alias);
1003    }
1004
1005    /**
1006     * Returns true if the entry identified by the given alias
1007     * was created by a call to <code>setCertificateEntry</code>,
1008     * or created by a call to <code>setEntry</code> with a
1009     * <code>TrustedCertificateEntry</code>.
1010     *
1011     * @param alias the alias for the keystore entry to be checked
1012     *
1013     * @return true if the entry identified by the given alias contains a
1014     * trusted certificate, false otherwise.
1015     *
1016     * @exception KeyStoreException if the keystore has not been initialized
1017     * (loaded).
1018     */

1019    public final boolean isCertificateEntry(String JavaDoc alias)
1020    throws KeyStoreException JavaDoc
1021    {
1022    if (!initialized) {
1023        throw new KeyStoreException JavaDoc("Uninitialized keystore");
1024    }
1025    return keyStoreSpi.engineIsCertificateEntry(alias);
1026    }
1027
1028    /**
1029     * Returns the (alias) name of the first keystore entry whose certificate
1030     * matches the given certificate.
1031     *
1032     * <p> This method attempts to match the given certificate with each
1033     * keystore entry. If the entry being considered was
1034     * created by a call to <code>setCertificateEntry</code>,
1035     * or created by a call to <code>setEntry</code> with a
1036     * <code>TrustedCertificateEntry</code>,
1037     * then the given certificate is compared to that entry's certificate.
1038     *
1039     * <p> If the entry being considered was
1040     * created by a call to <code>setKeyEntry</code>,
1041     * or created by a call to <code>setEntry</code> with a
1042     * <code>PrivateKeyEntry</code>,
1043     * then the given certificate is compared to the first
1044     * element of that entry's certificate chain.
1045     *
1046     * @param cert the certificate to match with.
1047     *
1048     * @return the alias name of the first entry with a matching certificate,
1049     * or null if no such entry exists in this keystore.
1050     *
1051     * @exception KeyStoreException if the keystore has not been initialized
1052     * (loaded).
1053     */

1054    public final String JavaDoc getCertificateAlias(Certificate JavaDoc cert)
1055    throws KeyStoreException JavaDoc
1056    {
1057    if (!initialized) {
1058        throw new KeyStoreException JavaDoc("Uninitialized keystore");
1059    }
1060    return keyStoreSpi.engineGetCertificateAlias(cert);
1061    }
1062
1063    /**
1064     * Stores this keystore to the given output stream, and protects its
1065     * integrity with the given password.
1066     *
1067     * @param stream the output stream to which this keystore is written.
1068     * @param password the password to generate the keystore integrity check
1069     *
1070     * @exception KeyStoreException if the keystore has not been initialized
1071     * (loaded).
1072     * @exception IOException if there was an I/O problem with data
1073     * @exception NoSuchAlgorithmException if the appropriate data integrity
1074     * algorithm could not be found
1075     * @exception CertificateException if any of the certificates included in
1076     * the keystore data could not be stored
1077     */

1078    public final void store(OutputStream stream, char[] password)
1079    throws KeyStoreException JavaDoc, IOException, NoSuchAlgorithmException JavaDoc,
1080        CertificateException JavaDoc
1081    {
1082    if (!initialized) {
1083        throw new KeyStoreException JavaDoc("Uninitialized keystore");
1084    }
1085    keyStoreSpi.engineStore(stream, password);
1086    }
1087
1088    /**
1089     * Stores this keystore using the given <code>LoadStoreParameter</code>.
1090     *
1091     * @param param the <code>LoadStoreParameter</code>
1092     * that specifies how to store the keystore,
1093     * which may be <code>null</code>
1094     *
1095     * @exception IllegalArgumentException if the given
1096     * <code>LoadStoreParameter</code>
1097     * input is not recognized
1098     * @exception KeyStoreException if the keystore has not been initialized
1099     * (loaded)
1100     * @exception IOException if there was an I/O problem with data
1101     * @exception NoSuchAlgorithmException if the appropriate data integrity
1102     * algorithm could not be found
1103     * @exception CertificateException if any of the certificates included in
1104     * the keystore data could not be stored
1105     *
1106     * @since 1.5
1107     */

1108    public final void store(LoadStoreParameter param)
1109        throws KeyStoreException JavaDoc, IOException,
1110        NoSuchAlgorithmException JavaDoc, CertificateException JavaDoc {
1111    if (!initialized) {
1112        throw new KeyStoreException JavaDoc("Uninitialized keystore");
1113    }
1114    keyStoreSpi.engineStore(param);
1115    }
1116
1117    /**
1118     * Loads this KeyStore from the given input stream.
1119     *
1120     * <p>A password may be given to unlock the keystore
1121     * (e.g. the keystore resides on a hardware token device),
1122     * or to check the integrity of the keystore data.
1123     * If a password is not given for integrity checking,
1124     * then integrity checking is not performed.
1125     *
1126     * <p>In order to create an empty keystore, or if the keystore cannot
1127     * be initialized from a stream, pass <code>null</code>
1128     * as the <code>stream</code> argument.
1129     *
1130     * <p> Note that if this keystore has already been loaded, it is
1131     * reinitialized and loaded again from the given input stream.
1132     *
1133     * @param stream the input stream from which the keystore is loaded,
1134     * or <code>null</code>
1135     * @param password the password used to check the integrity of
1136     * the keystore, the password used to unlock the keystore,
1137     * or <code>null</code>
1138     *
1139     * @exception IOException if there is an I/O or format problem with the
1140     * keystore data, if a password is required but not given,
1141     * or if the given password was incorrect
1142     * @exception NoSuchAlgorithmException if the algorithm used to check
1143     * the integrity of the keystore cannot be found
1144     * @exception CertificateException if any of the certificates in the
1145     * keystore could not be loaded
1146     */

1147    public final void load(InputStream stream, char[] password)
1148    throws IOException, NoSuchAlgorithmException JavaDoc, CertificateException JavaDoc
1149    {
1150    keyStoreSpi.engineLoad(stream, password);
1151    initialized = true;
1152    }
1153
1154    /**
1155     * Loads this keystore using the given <code>LoadStoreParameter</code>.
1156     *
1157     * <p> Note that if this KeyStore has already been loaded, it is
1158     * reinitialized and loaded again from the given parameter.
1159     *
1160     * @param param the <code>LoadStoreParameter</code>
1161     * that specifies how to load the keystore,
1162     * which may be <code>null</code>
1163     *
1164     * @exception IllegalArgumentException if the given
1165     * <code>LoadStoreParameter</code>
1166     * input is not recognized
1167     * @exception IOException if there is an I/O or format problem with the
1168     * keystore data
1169     * @exception NoSuchAlgorithmException if the algorithm used to check
1170     * the integrity of the keystore cannot be found
1171     * @exception CertificateException if any of the certificates in the
1172     * keystore could not be loaded
1173     *
1174     * @since 1.5
1175     */

1176    public final void load(LoadStoreParameter param)
1177        throws IOException, NoSuchAlgorithmException JavaDoc,
1178        CertificateException JavaDoc {
1179
1180    keyStoreSpi.engineLoad(param);
1181    initialized = true;
1182    }
1183
1184    /**
1185     * Gets a keystore <code>Entry</code> for the specified alias
1186     * with the specified protection parameter.
1187     *
1188     * @param alias get the keystore <code>Entry</code> for this alias
1189     * @param protParam the <code>ProtectionParameter</code>
1190     * used to protect the <code>Entry</code>,
1191     * which may be <code>null</code>
1192     *
1193     * @return the keystore <code>Entry</code> for the specified alias,
1194     * or <code>null</code> if there is no such entry
1195     *
1196     * @exception NullPointerException if
1197     * <code>alias</code> is <code>null</code>
1198     * @exception NoSuchAlgorithmException if the algorithm for recovering the
1199     * entry cannot be found
1200     * @exception UnrecoverableEntryException if the specified
1201     * <code>protParam</code> were insufficient or invalid
1202     * @exception KeyStoreException if the keystore has not been initialized
1203     * (loaded).
1204     * @see #setEntry(String, KeyStore.Entry, KeyStore.ProtectionParameter)
1205     *
1206     * @since 1.5
1207     */

1208    public final Entry getEntry(String JavaDoc alias, ProtectionParameter protParam)
1209            throws NoSuchAlgorithmException JavaDoc, UnrecoverableEntryException JavaDoc,
1210        KeyStoreException JavaDoc {
1211
1212    if (alias == null) {
1213        throw new NullPointerException JavaDoc("invalid null input");
1214    }
1215    if (!initialized) {
1216        throw new KeyStoreException JavaDoc("Uninitialized keystore");
1217    }
1218    return keyStoreSpi.engineGetEntry(alias, protParam);
1219    }
1220
1221    /**
1222     * Saves a keystore <code>Entry</code> under the specified alias.
1223     * The protection parameter is used to protect the
1224     * <code>Entry</code>.
1225     *
1226     * <p> If an entry already exists for the specified alias,
1227     * it is overridden.
1228     *
1229     * @param alias save the keystore <code>Entry</code> under this alias
1230     * @param entry the <code>Entry</code> to save
1231     * @param protParam the <code>ProtectionParameter</code>
1232     * used to protect the <code>Entry</code>,
1233     * which may be <code>null</code>
1234     *
1235     * @exception NullPointerException if
1236     * <code>alias</code> or <code>entry</code>
1237     * is <code>null</code>
1238     * @exception KeyStoreException if the keystore has not been initialized
1239     * (loaded), or if this operation fails for some other reason
1240     *
1241     * @see #getEntry(String, KeyStore.ProtectionParameter)
1242     *
1243     * @since 1.5
1244     */

1245    public final void setEntry(String JavaDoc alias, Entry entry,
1246            ProtectionParameter protParam)
1247        throws KeyStoreException JavaDoc {
1248    if (alias == null || entry == null) {
1249        throw new NullPointerException JavaDoc("invalid null input");
1250    }
1251    if (!initialized) {
1252        throw new KeyStoreException JavaDoc("Uninitialized keystore");
1253    }
1254    keyStoreSpi.engineSetEntry(alias, entry, protParam);
1255    }
1256
1257    /**
1258     * Determines if the keystore <code>Entry</code> for the specified
1259     * <code>alias</code> is an instance or subclass of the specified
1260     * <code>entryClass</code>.
1261     *
1262     * @param alias the alias name
1263     * @param entryClass the entry class
1264     *
1265     * @return true if the keystore <code>Entry</code> for the specified
1266     * <code>alias</code> is an instance or subclass of the
1267     * specified <code>entryClass</code>, false otherwise
1268     *
1269     * @exception NullPointerException if
1270     * <code>alias</code> or <code>entryClass</code>
1271     * is <code>null</code>
1272     * @exception KeyStoreException if the keystore has not been
1273     * initialized (loaded)
1274     *
1275     * @since 1.5
1276     */

1277    public final boolean
1278    entryInstanceOf(String JavaDoc alias,
1279            Class JavaDoc<? extends KeyStore.Entry JavaDoc> entryClass)
1280    throws KeyStoreException JavaDoc
1281    {
1282
1283    if (alias == null || entryClass == null) {
1284        throw new NullPointerException JavaDoc("invalid null input");
1285    }
1286    if (!initialized) {
1287        throw new KeyStoreException JavaDoc("Uninitialized keystore");
1288    }
1289    return keyStoreSpi.engineEntryInstanceOf(alias, entryClass);
1290    }
1291    
1292    /**
1293     * A description of a to-be-instantiated KeyStore object.
1294     *
1295     * <p>An instance of this class encapsulates the information needed to
1296     * instantiate and initialize a KeyStore object. That process is
1297     * triggered when the {@linkplain #getKeyStore} method is called.
1298     *
1299     * <p>This makes it possible to decouple configuration from KeyStore
1300     * object creation and e.g. delay a password prompt until it is
1301     * needed.
1302     *
1303     * @see KeyStore
1304     * @see javax.net.ssl.KeyStoreBuilderParameters
1305     * @since 1.5
1306     */

1307    public static abstract class Builder {
1308
1309    /**
1310     * Construct a new Builder.
1311     */

1312    protected Builder() {
1313        // empty
1314
}
1315
1316    /**
1317     * Returns the KeyStore described by this object.
1318     *
1319     * @exception KeyStoreException if an error occured during the
1320     * operation, for example if the KeyStore could not be
1321     * instantiated or loaded
1322     */

1323    public abstract KeyStore JavaDoc getKeyStore() throws KeyStoreException JavaDoc;
1324
1325    /**
1326     * Returns the ProtectionParameters that should be used to obtain
1327     * the {@link KeyStore.Entry Entry} with the given alias.
1328     * The <code>getKeyStore</code> method must be invoked before this
1329     * method may be called.
1330     *
1331     * @return the ProtectionParameters that should be used to obtain
1332     * the {@link KeyStore.Entry Entry} with the given alias.
1333     * @param alias the alias of the KeyStore entry
1334     * @throws NullPointerException if alias is null
1335     * @throws KeyStoreException if an error occured during the
1336     * operation
1337     * @throws IllegalStateException if the getKeyStore method has
1338     * not been invoked prior to calling this method
1339     */

1340    public abstract ProtectionParameter getProtectionParameter(String JavaDoc alias)
1341        throws KeyStoreException JavaDoc;
1342
1343    /**
1344     * Returns a new Builder that encapsulates the given KeyStore.
1345     * The {@linkplain #getKeyStore} method of the returned object
1346     * will return <code>keyStore</code>, the {@linkplain
1347     * #getProtectionParameter getProtectionParameter()} method will
1348     * return <code>protectionParameters</code>.
1349         *
1350     * <p> This is useful if an existing KeyStore object needs to be
1351     * used with Builder-based APIs.
1352     *
1353     * @return a new Builder object
1354     * @param keyStore the KeyStore to be encapsulated
1355     * @param protectionParameter the ProtectionParameter used to
1356     * protect the KeyStore entries
1357     * @throws NullPointerException if keyStore or
1358     * protectionParameters is null
1359     * @throws IllegalArgumentException if the keyStore has not been
1360     * initialized
1361     */

1362    public static Builder newInstance(final KeyStore JavaDoc keyStore,
1363        final ProtectionParameter protectionParameter) {
1364        if ((keyStore == null) || (protectionParameter == null)) {
1365        throw new NullPointerException JavaDoc();
1366        }
1367        if (keyStore.initialized == false) {
1368        throw new IllegalArgumentException JavaDoc("KeyStore not initialized");
1369        }
1370        return new Builder() {
1371        private volatile boolean getCalled;
1372        
1373        public KeyStore JavaDoc getKeyStore() {
1374            getCalled = true;
1375            return keyStore;
1376        }
1377        
1378        public ProtectionParameter getProtectionParameter(String JavaDoc alias)
1379        {
1380            if (alias == null) {
1381            throw new NullPointerException JavaDoc();
1382            }
1383            if (getCalled == false) {
1384            throw new IllegalStateException JavaDoc
1385                ("getKeyStore() must be called first");
1386            }
1387            return protectionParameter;
1388        }
1389        };
1390    }
1391
1392    /**
1393     * Returns a new Builder object.
1394     *
1395     * <p>The first call to the {@link #getKeyStore} method on the returned
1396     * builder will create a KeyStore of type <code>type</code> and call
1397     * its {@link KeyStore#load load()} method.
1398     * The <code>inputStream</code> argument is constructed from
1399     * <code>file</code>.
1400     * If <code>protection</code> is a
1401     * <code>PasswordProtection</code>, the password is obtained by
1402     * calling the <code>getPassword</code> method.
1403     * Otherwise, if <code>protection</code> is a
1404     * <code>CallbackHandlerProtection</code>, the password is obtained
1405     * by invoking the CallbackHandler.
1406     *
1407     * <p>Subsequent calls to {@link #getKeyStore} return the same object
1408     * as the initial call. If the initial call to failed with a
1409     * KeyStoreException, subsequent calls also throw a
1410     * KeyStoreException.
1411     *
1412     * <p>The KeyStore is instantiated from <code>provider</code> if
1413     * non-null. Otherwise, all installed providers are searched.
1414     *
1415     * <p>Calls to {@link #getProtectionParameter getProtectionParameter()}
1416     * will return a {@link KeyStore.PasswordProtection PasswordProtection}
1417     * object encapsulating the password that was used to invoke the
1418     * <code>load</code> method.
1419     *
1420     * <p><em>Note</em> that the {@link #getKeyStore} method is executed
1421     * within the {@link AccessControlContext} of the code invoking this
1422     * method.
1423     *
1424     * @return a new Builder object
1425     * @param type the type of KeyStore to be constructed
1426     * @param provider the provider from which the KeyStore is to
1427     * be instantiated (or null)
1428     * @param file the File that contains the KeyStore data
1429     * @param protection the ProtectionParameter securing the KeyStore data
1430     * @throws NullPointerException if type, file or protection is null
1431     * @throws IllegalArgumentException if protection is not an instance
1432     * of either PasswordProtection or CallbackHandlerProtection; or
1433     * if file does not exist or does not refer to a normal file
1434     */

1435    public static Builder newInstance(String JavaDoc type, Provider JavaDoc provider,
1436        File file, ProtectionParameter protection) {
1437        if ((type == null) || (file == null) || (protection == null)) {
1438        throw new NullPointerException JavaDoc();
1439        }
1440        if ((protection instanceof PasswordProtection == false) &&
1441        (protection instanceof CallbackHandlerProtection == false)) {
1442        throw new IllegalArgumentException JavaDoc
1443        ("Protection must be PasswordProtection or " +
1444         "CallbackHandlerProtection");
1445        }
1446        if (file.isFile() == false) {
1447        throw new IllegalArgumentException JavaDoc
1448            ("File does not exist or it does not refer " +
1449             "to a normal file: " + file);
1450        }
1451        return new FileBuilder(type, provider, file, protection,
1452        AccessController.getContext());
1453    }
1454    
1455    private static final class FileBuilder extends Builder {
1456        
1457        private final String JavaDoc type;
1458        private final Provider JavaDoc provider;
1459        private final File file;
1460        private ProtectionParameter protection;
1461        private final AccessControlContext JavaDoc context;
1462        
1463        private KeyStore JavaDoc keyStore;
1464        
1465        private Throwable JavaDoc oldException;
1466        
1467        FileBuilder(String JavaDoc type, Provider JavaDoc provider, File file,
1468            ProtectionParameter protection,
1469            AccessControlContext JavaDoc context) {
1470        this.type = type;
1471        this.provider = provider;
1472        this.file = file;
1473        this.protection = protection;
1474        this.context = context;
1475        }
1476        
1477        public synchronized KeyStore JavaDoc getKeyStore() throws KeyStoreException JavaDoc
1478        {
1479        if (keyStore != null) {
1480            return keyStore;
1481        }
1482        if (oldException != null) {
1483            throw new KeyStoreException JavaDoc
1484            ("Previous KeyStore instantiation failed",
1485             oldException);
1486        }
1487        PrivilegedExceptionAction JavaDoc action =
1488            new PrivilegedExceptionAction JavaDoc() {
1489            public Object JavaDoc run() throws Exception JavaDoc {
1490            KeyStore JavaDoc ks;
1491            if (provider == null) {
1492                ks = KeyStore.getInstance(type);
1493            } else {
1494                ks = KeyStore.getInstance(type, provider);
1495            }
1496            InputStream in = null;
1497            char[] password = null;
1498            try {
1499                in = new FileInputStream(file);
1500                if (protection instanceof PasswordProtection) {
1501                password =
1502                ((PasswordProtection)protection).getPassword();
1503                } else {
1504                CallbackHandler handler =
1505                    ((CallbackHandlerProtection)protection)
1506                    .getCallbackHandler();
1507                PasswordCallback callback = new PasswordCallback
1508                    ("Password for keystore " + file.getName(),
1509                    false);
1510                handler.handle(new Callback[] {callback});
1511                password = callback.getPassword();
1512                if (password == null) {
1513                    throw new KeyStoreException JavaDoc("No password" +
1514                                " provided");
1515                }
1516                callback.clearPassword();
1517                protection = new PasswordProtection(password);
1518                }
1519                ks.load(in, password);
1520                return ks;
1521            } finally {
1522                if (in != null) {
1523                in.close();
1524                }
1525            }
1526            }
1527        };
1528        try {
1529            keyStore = (KeyStore JavaDoc)AccessController.doPrivileged
1530                            (action, context);
1531            return keyStore;
1532        } catch (PrivilegedActionException JavaDoc e) {
1533            oldException = e.getCause();
1534            throw new KeyStoreException JavaDoc
1535            ("KeyStore instantiation failed", oldException);
1536        }
1537        }
1538        
1539        public synchronized ProtectionParameter
1540            getProtectionParameter(String JavaDoc alias) {
1541        if (alias == null) {
1542            throw new NullPointerException JavaDoc();
1543        }
1544        if (keyStore == null) {
1545            throw new IllegalStateException JavaDoc
1546            ("getKeyStore() must be called first");
1547        }
1548        return protection;
1549        }
1550    }
1551    
1552    /**
1553     * Returns a new Builder object.
1554     *
1555     * <p>Each call to the {@link #getKeyStore} method on the returned
1556     * builder will return a new KeyStore object of type <code>type</code>.
1557     * Its {@link KeyStore#load(KeyStore.LoadStoreParameter) load()}
1558     * method is invoked using a
1559     * <code>LoadStoreParameter</code> that encapsulates
1560     * <code>protection</code>.
1561     *
1562     * <p>The KeyStore is instantiated from <code>provider</code> if
1563     * non-null. Otherwise, all installed providers are searched.
1564     *
1565     * <p>Calls to {@link #getProtectionParameter getProtectionParameter()}
1566     * will return <code>protection</code>.
1567     *
1568     * <p><em>Note</em> that the {@link #getKeyStore} method is executed
1569     * within the {@link AccessControlContext} of the code invoking this
1570     * method.
1571     *
1572     * @return a new Builder object
1573     * @param type the type of KeyStore to be constructed
1574     * @param provider the provider from which the KeyStore is to
1575     * be instantiated (or null)
1576     * @param protection the ProtectionParameter securing the Keystore
1577     * @throws NullPointerException if type or protection is null
1578     */

1579    public static Builder newInstance(final String JavaDoc type,
1580        final Provider JavaDoc provider, final ProtectionParameter protection) {
1581        if ((type == null) || (protection == null)) {
1582        throw new NullPointerException JavaDoc();
1583        }
1584        final AccessControlContext JavaDoc context = AccessController.getContext();
1585        return new Builder() {
1586        private volatile boolean getCalled;
1587        
1588        private final PrivilegedExceptionAction JavaDoc action
1589        = new PrivilegedExceptionAction JavaDoc() {
1590            
1591            public Object JavaDoc run() throws Exception JavaDoc {
1592            KeyStore JavaDoc ks;
1593            if (provider == null) {
1594                ks = KeyStore.getInstance(type);
1595            } else {
1596                ks = KeyStore.getInstance(type, provider);
1597            }
1598            ks.load(new SimpleLoadStoreParameter(protection));
1599            getCalled = true;
1600            return ks;
1601            }
1602        };
1603        
1604        public synchronized KeyStore JavaDoc getKeyStore()
1605            throws KeyStoreException JavaDoc {
1606            try {
1607            return (KeyStore JavaDoc)AccessController.doPrivileged(action);
1608            } catch (PrivilegedActionException JavaDoc e) {
1609            Throwable JavaDoc cause = e.getCause();
1610            throw new KeyStoreException JavaDoc
1611                ("KeyStore instantiation failed", cause);
1612            }
1613        }
1614        
1615        public ProtectionParameter getProtectionParameter(String JavaDoc alias)
1616        {
1617            if (alias == null) {
1618            throw new NullPointerException JavaDoc();
1619            }
1620            if (getCalled == false) {
1621            throw new IllegalStateException JavaDoc
1622                ("getKeyStore() must be called first");
1623            }
1624            return protection;
1625        }
1626        };
1627    }
1628
1629    }
1630    
1631    static class SimpleLoadStoreParameter implements LoadStoreParameter {
1632    
1633    private final ProtectionParameter protection;
1634    
1635    SimpleLoadStoreParameter(ProtectionParameter protection) {
1636        this.protection = protection;
1637    }
1638    
1639    public ProtectionParameter getProtectionParameter() {
1640        return protection;
1641    }
1642    }
1643    
1644}
1645
1646
Popular Tags