View Javadoc
1   /*
2    * #%L
3    * Credential.java - mongodb-async-driver - Allanbank Consulting, Inc.
4    * %%
5    * Copyright (C) 2011 - 2014 Allanbank Consulting, Inc.
6    * %%
7    * Licensed under the Apache License, Version 2.0 (the "License");
8    * you may not use this file except in compliance with the License.
9    * You may obtain a copy of the License at
10   * 
11   *      http://www.apache.org/licenses/LICENSE-2.0
12   * 
13   * Unless required by applicable law or agreed to in writing, software
14   * distributed under the License is distributed on an "AS IS" BASIS,
15   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16   * See the License for the specific language governing permissions and
17   * limitations under the License.
18   * #L%
19   */
20  package com.allanbank.mongodb;
21  
22  import java.io.File;
23  import java.io.IOException;
24  import java.io.ObjectInputStream;
25  import java.io.Serializable;
26  import java.security.cert.X509Certificate;
27  import java.util.Arrays;
28  import java.util.Collections;
29  import java.util.HashMap;
30  import java.util.Map;
31  
32  import com.allanbank.mongodb.client.connection.auth.Authenticator;
33  import com.allanbank.mongodb.client.connection.auth.MongoDbAuthenticator;
34  import com.allanbank.mongodb.error.MongoDbAuthenticationException;
35  
36  /**
37   * Credential provides an immutable set of credential for accessing MongoDB.
38   * <p>
39   * A given client can support a different set of credential for each database
40   * the client is accessing. The client can also authenticate against the
41   * {@value #ADMIN_DB} database which will apply across all databases.
42   * </p>
43   * <p>
44   * <em>Note:</em> While we use the term user name/password within this class the
45   * values may not actually be a user name or a password. In addition not all
46   * authentication mechanisms may use all of the fields in this class. See the
47   * documentation for the authenticator being used for details on what values are
48   * expected for each of the fields in this class.
49   * </p>
50   * 
51   * @see <a
52   *      href="http://www.allanbank.com/mongodb-async-driver/userguide/authentication.html">Authentication
53   *      Usage Guide</a>
54   * @api.yes This class is part of the driver's API. Public and protected members
55   *          will be deprecated for at least 1 non-bugfix release (version
56   *          numbers are &lt;major&gt;.&lt;minor&gt;.&lt;bugfix&gt;) before being
57   *          removed or modified.
58   * @copyright 2013, Allanbank Consulting, Inc., All Rights Reserved
59   */
60  public final class Credential implements Serializable {
61  
62      /**
63       * The name of the administration database used to authenticate a
64       * administrator to MongoDB.
65       */
66      public static final String ADMIN_DB = "admin";
67  
68      /**
69       * Constant for Kerberos authentication.
70       * <p>
71       * <em>Note:</em> Use of the Kerberos for authentication requires the
72       * driver's extensions. See the <a href=
73       * "http://www.allanbank.com/mongodb-async-driver/userguide/authentication/kerberos.html"
74       * >Kerberos Usage Guide</a> for details.
75       * </p>
76       * 
77       * @see <a
78       *      href="http://www.allanbank.com/mongodb-async-driver/userguide/authentication/kerberos.html">Kerberos
79       *      Usage Guide</a>
80       */
81      public static final String KERBEROS;
82  
83      /** Constant for traditional MongoDB Challenge/Response. */
84      public static final String MONGODB_CR;
85  
86      /** An empty password array. */
87      public static final char[] NO_PASSWORD = new char[0];
88  
89      /**
90       * Constant for authentication using plain SASL (LDAP/PAM) client
91       * certificates passed at connection establishment.
92       * <p>
93       * <em>Note:</em> Use of Plain SASL for authentication requires the driver's
94       * extensions. See the <a href=
95       * "http://www.allanbank.com/mongodb-async-driver/userguide/authentication/plain_sasl.html"
96       * >Plain SASL Usage Guide</a> for details.
97       * </p>
98       * 
99       * @see <a
100      *      href="http://www.allanbank.com/mongodb-async-driver/userguide/authentication/plain_sasl.html">Plain
101      *      SASL Usage Guide</a>
102      */
103     public static final String PLAIN_SASL;
104 
105     /**
106      * Constant for authentication using x.509 client certificates passed at
107      * connection establishment.
108      * <p>
109      * <em>Note:</em> Use of the x.509 for authentication requires the driver's
110      * extensions. See the <a href=
111      * "http://www.allanbank.com/mongodb-async-driver/userguide/authentication/tls.html"
112      * >TLS/SSL Usage Guide</a> for details.
113      * </p>
114      * 
115      * @see <a
116      *      href="http://www.allanbank.com/mongodb-async-driver/userguide/authentication/tls.html">TLS/SSL
117      *      Usage Guide</a>
118      * @see <a
119      *      href="http://www.allanbank.com/mongodb-async-driver/userguide/authentication/x509.html">x.509
120      *      Authentication Usage Guide</a>
121      */
122     public static final String X509;
123 
124     /** Serialization version of the class. */
125     private static final long serialVersionUID = -6251469373336569336L;
126 
127     static {
128         KERBEROS = "com.allanbank.mongodb.extensions.authentication.KerberosAuthenticator";
129         MONGODB_CR = MongoDbAuthenticator.class.getName();
130         PLAIN_SASL = "com.allanbank.mongodb.extensions.authentication.PlainSaslAuthenticator";
131         X509 = "com.allanbank.mongodb.extensions.authentication.X509Authenticator";
132     }
133 
134     /**
135      * Creates a {@link Builder} for creating a {@link Credential}.
136      * 
137      * @return The {@link Builder} for creating a {@link Credential}.
138      */
139     public static Builder builder() {
140         return new Builder();
141     }
142 
143     /**
144      * The authentication type or mode that the credential should be used with.
145      */
146     private final String myAuthenticationType;
147 
148     /** The template authenticator for the credential. */
149     private transient Authenticator myAuthenticator;
150 
151     /** The database the credential are valid for. */
152     private final String myDatabase;
153 
154     /** The file containing the full credentials. */
155     private final File myFile;
156 
157     /** Other options for the credentials. */
158     private final Map<String, String> myOptions;
159 
160     /** The password for the credential set. */
161     private final char[] myPassword;
162 
163     /** The user name for the credential set. */
164     private final String myUserName;
165 
166     /**
167      * Creates a new Credential.
168      * 
169      * @param builder
170      *            The builder for the credentials.
171      */
172     public Credential(final Builder builder) {
173         myUserName = builder.myUserName;
174         myDatabase = builder.myDatabase;
175         myFile = builder.myFile;
176         myAuthenticationType = builder.myAuthenticationType;
177         myAuthenticator = builder.myAuthenticator;
178         myPassword = builder.myPassword.clone();
179         myOptions = Collections.unmodifiableMap(new HashMap<String, String>(
180                 builder.myOptions));
181     }
182 
183     /**
184      * Returns an authenticator for the credential.
185      * 
186      * @return The authenticator for the credential.
187      * @throws MongoDbAuthenticationException
188      *             On a failure to load the authenticator for the credential.
189      */
190     public Authenticator authenticator() throws MongoDbAuthenticationException {
191         if (myAuthenticator == null) {
192             try {
193                 loadAuthenticator();
194             }
195             catch (final ClassNotFoundException e) {
196                 throw new MongoDbAuthenticationException(e);
197             }
198             catch (final InstantiationException e) {
199                 throw new MongoDbAuthenticationException(e);
200             }
201             catch (final IllegalAccessException e) {
202                 throw new MongoDbAuthenticationException(e);
203             }
204         }
205 
206         return myAuthenticator.clone();
207     }
208 
209     /**
210      * {@inheritDoc}
211      * <p>
212      * Overridden to return true if the passed value equals these credential.
213      * </p>
214      */
215     @Override
216     public boolean equals(final Object object) {
217         boolean result = false;
218         if (this == object) {
219             result = true;
220         }
221         else if ((object != null) && (getClass() == object.getClass())) {
222             final Credential other = (Credential) object;
223 
224             result = nullSafeEquals(myAuthenticationType,
225                     other.myAuthenticationType)
226                     && nullSafeEquals(myDatabase, other.myDatabase)
227                     && nullSafeEquals(myUserName, other.myUserName)
228                     && nullSafeEquals(myFile, other.myFile)
229                     && nullSafeEquals(myOptions, other.myOptions)
230                     && Arrays.equals(myPassword, other.myPassword);
231         }
232         return result;
233     }
234 
235     /**
236      * Returns the authentication type or mode that the credential should be
237      * used with.
238      * 
239      * @return The authentication type or mode that the credential should be
240      *         used with.
241      */
242     public String getAuthenticationType() {
243         return myAuthenticationType;
244     }
245 
246     /**
247      * Returns the authenticator value.
248      * 
249      * @return The authenticator value.
250      */
251     public Authenticator getAuthenticator() {
252         return myAuthenticator;
253     }
254 
255     /**
256      * Returns the database the credential are valid for. Use {@link #ADMIN_DB}
257      * to authenticate as an administrator.
258      * 
259      * @return The database the credential are valid for.
260      */
261     public String getDatabase() {
262         return myDatabase;
263     }
264 
265     /**
266      * Returns the file containing the full credentials.
267      * 
268      * @return The file containing the full credentials. May be
269      *         <code>null</code>.
270      */
271     public File getFile() {
272         return myFile;
273     }
274 
275     /**
276      * Returns the option value.
277      * 
278      * @param optionName
279      *            The name of the option to set.
280      * @param defaultValue
281      *            The value of the option if it is not set or cannot be parsed
282      *            via {@link Boolean#parseBoolean(String)}.
283      * @return The option value.
284      */
285     public boolean getOption(final String optionName, final boolean defaultValue) {
286         final String value = myOptions.get(optionName);
287         if (value != null) {
288             return Boolean.parseBoolean(value);
289         }
290         return defaultValue;
291     }
292 
293     /**
294      * Returns the option value.
295      * 
296      * @param optionName
297      *            The name of the option to set.
298      * @param defaultValue
299      *            The value of the option if it is not set or cannot be parsed
300      *            via {@link Integer#parseInt(String)}.
301      * @return The option value.
302      */
303     public int getOption(final String optionName, final int defaultValue) {
304         final String value = myOptions.get(optionName);
305         if (value != null) {
306             try {
307                 return Integer.parseInt(value);
308             }
309             catch (final NumberFormatException nfe) {
310                 return defaultValue;
311             }
312         }
313         return defaultValue;
314     }
315 
316     /**
317      * Returns the option value.
318      * 
319      * @param optionName
320      *            The name of the option to set.
321      * @param defaultValue
322      *            The value of the option if it is not set.
323      * @return The option value.
324      */
325     public String getOption(final String optionName, final String defaultValue) {
326         String value = myOptions.get(optionName);
327         if (value == null) {
328             value = defaultValue;
329         }
330 
331         return value;
332     }
333 
334     /**
335      * Returns the password for the credential set. A clone of the internal
336      * array is returns that should be cleared when it is done being used via
337      * something like {@link java.util.Arrays#fill(char[], char)
338      * Arrays.fill(password, 0)}
339      * 
340      * @return The password for the credential set.
341      */
342     public char[] getPassword() {
343         return myPassword.clone();
344     }
345 
346     /**
347      * Returns the user name for the credential set.
348      * 
349      * @return The user name for the credential set.
350      */
351     public String getUserName() {
352         return myUserName;
353     }
354 
355     /**
356      * {@inheritDoc}
357      * <p>
358      * Overridden to hash the credential.
359      * </p>
360      */
361     @Override
362     public int hashCode() {
363         int result = 1;
364 
365         result = (31 * result)
366                 + ((myAuthenticationType == null) ? 0 : myAuthenticationType
367                         .hashCode());
368         result = (31 * result)
369                 + ((myDatabase == null) ? 0 : myDatabase.hashCode());
370         result = (31 * result) + myOptions.hashCode();
371         result = (31 * result) + Arrays.hashCode(myPassword);
372         result = (31 * result)
373                 + ((myUserName == null) ? 0 : myUserName.hashCode());
374         result = (31 * result) + ((myFile == null) ? 0 : myFile.hashCode());
375 
376         return result;
377     }
378 
379     /**
380      * Returns true if the password has atleast a single character.
381      * 
382      * @return True if the password has atleast a single character, false
383      *         otherwise.
384      */
385     public boolean hasPassword() {
386         return (myPassword.length > 0);
387     }
388 
389     /**
390      * {@inheritDoc}
391      * <p>
392      * Overridden to returns the credential in a human readable form.
393      * </p>
394      */
395     @Override
396     public String toString() {
397         final StringBuilder builder = new StringBuilder();
398         builder.append("{ username : '");
399         builder.append(myUserName);
400         builder.append("', database : '");
401         builder.append(myDatabase);
402         if (myFile != null) {
403             builder.append("', file : '");
404             builder.append(myFile.getName());
405         }
406         builder.append("', password : '<redacted>', type: '");
407         if (KERBEROS.equals(myAuthenticationType)) {
408             builder.append("KERBEROS");
409         }
410         else if (PLAIN_SASL.equals(myAuthenticationType)) {
411             builder.append("PLAIN SASL");
412         }
413         else if (X509.equals(myAuthenticationType)) {
414             builder.append("x.509");
415         }
416         else if (MONGODB_CR.equals(myAuthenticationType)) {
417             builder.append("MONGODB-CR");
418         }
419         else if (myAuthenticationType != null) {
420             builder.append(myAuthenticationType);
421         }
422 
423         for (final Map.Entry<String, String> option : myOptions.entrySet()) {
424             builder.append("', '");
425             builder.append(option.getKey());
426             builder.append("': '");
427             builder.append(option.getValue());
428         }
429 
430         builder.append("' }");
431 
432         return builder.toString();
433     }
434 
435     /**
436      * Loads the authenticator for the credential.
437      * 
438      * @throws ClassNotFoundException
439      *             If the authenticators Class cannot be found.
440      * @throws InstantiationException
441      *             If the authenticator cannot be instantiated.
442      * @throws IllegalAccessException
443      *             If the authenticator cannot be accessed.
444      */
445     /* package */void loadAuthenticator() throws ClassNotFoundException,
446             InstantiationException, IllegalAccessException {
447         if (myAuthenticator == null) {
448             myAuthenticator = (Authenticator) Class.forName(
449                     getAuthenticationType()).newInstance();
450         }
451     }
452 
453     /**
454      * Does a null safe equals comparison.
455      * 
456      * @param rhs
457      *            The right-hand-side of the comparison.
458      * @param lhs
459      *            The left-hand-side of the comparison.
460      * @return True if the rhs equals the lhs. Note: nullSafeEquals(null, null)
461      *         returns true.
462      */
463     private boolean nullSafeEquals(final Object rhs, final Object lhs) {
464         return (rhs == lhs) || ((rhs != null) && rhs.equals(lhs));
465     }
466 
467     /**
468      * Sets the transient state of this {@link Credential}.
469      * 
470      * @param in
471      *            The input stream.
472      * @throws ClassNotFoundException
473      *             On a failure loading a class in this classed reachable tree.
474      * @throws IOException
475      *             On a failure reading from the stream.
476      */
477     private void readObject(final ObjectInputStream in)
478             throws ClassNotFoundException, IOException {
479         in.defaultReadObject();
480         myAuthenticator = null;
481     }
482 
483     /**
484      * Builder provides a helper for creating a {@link Credential}.
485      * 
486      * @copyright 2013, Allanbank Consulting, Inc., All Rights Reserved
487      */
488     public static class Builder {
489         /**
490          * The authentication type or mode that the credential should be used
491          * with.
492          */
493         protected String myAuthenticationType;
494 
495         /** The template authenticator for the credential. */
496         protected Authenticator myAuthenticator;
497 
498         /** The database the credential are valid for. */
499         protected String myDatabase;
500 
501         /** The file containing the full credentials. */
502         protected File myFile;
503 
504         /** Other options for the credentials. */
505         protected final Map<String, String> myOptions;
506 
507         /** The password for the credential set. */
508         protected char[] myPassword;
509 
510         /** The user name for the credential set. */
511         protected String myUserName;
512 
513         /**
514          * Creates a new Builder.
515          */
516         public Builder() {
517             myOptions = new HashMap<String, String>();
518             reset();
519         }
520 
521         /**
522          * Adds an option to the built credentials.
523          * 
524          * @param optionName
525          *            The name of the option to set.
526          * @param optionValue
527          *            The value of the option to set.
528          * @return This {@link Builder} for method chaining.
529          */
530         public Builder addOption(final String optionName,
531                 final boolean optionValue) {
532             myOptions.put(optionName, String.valueOf(optionValue));
533 
534             return this;
535         }
536 
537         /**
538          * Adds an option to the built credentials.
539          * 
540          * @param optionName
541          *            The name of the option to set.
542          * @param optionValue
543          *            The value of the option to set.
544          * @return This {@link Builder} for method chaining.
545          */
546         public Builder addOption(final String optionName, final int optionValue) {
547             myOptions.put(optionName, String.valueOf(optionValue));
548 
549             return this;
550         }
551 
552         /**
553          * Adds an option to the built credentials.
554          * 
555          * @param optionName
556          *            The name of the option to set.
557          * @param optionValue
558          *            The value of the option to set.
559          * @return This {@link Builder} for method chaining.
560          */
561         public Builder addOption(final String optionName,
562                 final String optionValue) {
563             myOptions.put(optionName, optionValue);
564 
565             return this;
566         }
567 
568         /**
569          * Sets the value of the authentication type or mode that the credential
570          * should be used with.
571          * <p>
572          * This method delegates to {@link #setAuthenticationType(String)}.
573          * </p>
574          * 
575          * @param authenticationType
576          *            The new value for the authentication type or mode that the
577          *            credential should be used with.
578          * @return This {@link Builder} for method chaining.
579          */
580         public Builder authenticationType(final String authenticationType) {
581             return setAuthenticationType(authenticationType);
582         }
583 
584         /**
585          * Sets the value of the template authenticator for the credential.
586          * <p>
587          * This method delegates to {@link #setAuthenticator(Authenticator)}.
588          * </p>
589          * 
590          * @param authenticator
591          *            The new value for the template authenticator for the
592          *            credential.
593          * @return This {@link Builder} for method chaining.
594          */
595         public Builder authenticator(final Authenticator authenticator) {
596             return setAuthenticator(authenticator);
597         }
598 
599         /**
600          * Creates the credential from this builder.
601          * 
602          * @return The {@link Credential} populated with the state of this
603          *         builder.
604          */
605         public Credential build() {
606             return new Credential(this);
607         }
608 
609         /**
610          * Sets the value of the database the credential are valid for.
611          * <p>
612          * This method delegates to {@link #setDatabase(String)}.
613          * </p>
614          * 
615          * @param database
616          *            The new value for the database the credential are valid
617          *            for.
618          * @return This {@link Builder} for method chaining.
619          */
620         public Builder database(final String database) {
621             return setDatabase(database);
622         }
623 
624         /**
625          * Sets the value of the file containing the full credentials.
626          * <p>
627          * This method delegates to {@link #setFile(File)}.
628          * </p>
629          * 
630          * @param file
631          *            The new value for the file containing the full
632          *            credentials.
633          * @return This {@link Builder} for method chaining.
634          */
635         public Builder file(final File file) {
636             return setFile(file);
637         }
638 
639         /**
640          * Sets the value of the authentication type or mode that the credential
641          * should be used with to Kerberos.
642          * <p>
643          * This method delegates to {@link #setAuthenticationType(String)
644          * setAuthenticationType(KERBEROS)}.
645          * </p>
646          * <p>
647          * <em>Note:</em> Use of Kerberos for authentication requires the
648          * driver's extensions. See the <a href=
649          * "http://www.allanbank.com/mongodb-async-driver/userguide/authentication/kerberos.html"
650          * >Kerberos Usage Guide</a> for details.
651          * </p>
652          * 
653          * @see <a
654          *      href="http://www.allanbank.com/mongodb-async-driver/userguide/authentication/kerberos.html">Kerberos
655          *      Usage Guide</a>
656          * 
657          * @return This {@link Builder} for method chaining.
658          */
659         public Builder kerberos() {
660             return setAuthenticationType(KERBEROS);
661         }
662 
663         /**
664          * Sets the value of the authentication type or mode that the credential
665          * should be used with LDAP via PLAIN SASL.
666          * <p>
667          * This method delegates to {@link #setAuthenticationType(String)
668          * setAuthenticationType(PLAIN_SASL)}.
669          * </p>
670          * <p>
671          * <em>Note:</em> Use of Plain SASL for authentication requires the
672          * driver's extensions. See the <a href=
673          * "http://www.allanbank.com/mongodb-async-driver/userguide/authentication/plain_sasl.html"
674          * >Plain SASL Usage Guide</a> for details.
675          * </p>
676          * 
677          * @see <a
678          *      href="http://www.allanbank.com/mongodb-async-driver/userguide/authentication/plain_sasl.html">Plain
679          *      SASL Usage Guide</a>
680          * 
681          * @return This {@link Builder} for method chaining.
682          */
683         public Builder ldap() {
684             return setAuthenticationType(PLAIN_SASL);
685         }
686 
687         /**
688          * Sets the value of the authentication type or mode that the credential
689          * should be used with to MongoDB Challenge/Response.
690          * <p>
691          * This method delegates to {@link #setAuthenticationType(String)
692          * setAuthenticationType(MONGODB_CR)}.
693          * </p>
694          * 
695          * @return This {@link Builder} for method chaining.
696          */
697         public Builder mongodbCR() {
698             return setAuthenticationType(MONGODB_CR);
699         }
700 
701         /**
702          * Sets the value of the authentication type or mode that the credential
703          * should be used with PAM via PLAIN SASL.
704          * <p>
705          * This method delegates to {@link #setAuthenticationType(String)
706          * setAuthenticationType(PLAIN_SASL)}.
707          * </p>
708          * <p>
709          * <em>Note:</em> Use of Plain SASL for authentication requires the
710          * driver's extensions. See the <a href=
711          * "http://www.allanbank.com/mongodb-async-driver/userguide/authentication/plain_sasl.html"
712          * >Plain SASL Usage Guide</a> for details.
713          * </p>
714          * 
715          * @see <a
716          *      href="http://www.allanbank.com/mongodb-async-driver/userguide/authentication/plain_sasl.html">Plain
717          *      SASL Usage Guide</a>
718          * 
719          * @return This {@link Builder} for method chaining.
720          */
721         public Builder pam() {
722             return setAuthenticationType(PLAIN_SASL);
723         }
724 
725         /**
726          * Sets the value of the password for the credential set.
727          * <p>
728          * This method delegates to {@link #setPassword(char[])}.
729          * </p>
730          * 
731          * @param password
732          *            The new value for the password for the credential set.
733          * @return This {@link Builder} for method chaining.
734          */
735         public Builder password(final char[] password) {
736             return setPassword(password);
737         }
738 
739         /**
740          * Sets the value of the authentication type or mode that the credential
741          * should be used with to PLAIN SASL.
742          * <p>
743          * This method delegates to {@link #setAuthenticationType(String)
744          * setAuthenticationType(PLAIN_SASL)}.
745          * </p>
746          * <p>
747          * <em>Note:</em> Use of Plain SASL for authentication requires the
748          * driver's extensions. See the <a href=
749          * "http://www.allanbank.com/mongodb-async-driver/userguide/authentication/plain_sasl.html"
750          * >Plain SASL Usage Guide</a> for details.
751          * </p>
752          * 
753          * @see <a
754          *      href="http://www.allanbank.com/mongodb-async-driver/userguide/authentication/plain_sasl.html">Plain
755          *      SASL Usage Guide</a>
756          * 
757          * @return This {@link Builder} for method chaining.
758          */
759         public Builder plainSasl() {
760             return setAuthenticationType(PLAIN_SASL);
761         }
762 
763         /**
764          * Resets the builder to a known state.
765          * 
766          * @return This {@link Builder} for method chaining.
767          */
768         public Builder reset() {
769             if (myPassword != null) {
770                 Arrays.fill(myPassword, '\u0000');
771             }
772 
773             myAuthenticationType = MONGODB_CR;
774             myAuthenticator = null;
775             myDatabase = ADMIN_DB;
776             myFile = null;
777             myPassword = NO_PASSWORD;
778             myUserName = null;
779             myOptions.clear();
780 
781             return this;
782         }
783 
784         /**
785          * Sets the value of the authentication type or mode that the credential
786          * should be used with.
787          * 
788          * @param authenticationType
789          *            The new value for the authentication type or mode that the
790          *            credential should be used with.
791          * @return This {@link Builder} for method chaining.
792          */
793         public Builder setAuthenticationType(final String authenticationType) {
794             myAuthenticationType = authenticationType;
795             return this;
796         }
797 
798         /**
799          * Sets the value of the template authenticator for the credential.
800          * 
801          * @param authenticator
802          *            The new value for the template authenticator for the
803          *            credential.
804          * @return This {@link Builder} for method chaining.
805          */
806         public Builder setAuthenticator(final Authenticator authenticator) {
807             myAuthenticator = authenticator;
808             return this;
809         }
810 
811         /**
812          * Sets the value of the database the credential are valid for.
813          * 
814          * @param database
815          *            The new value for the database the credential are valid
816          *            for.
817          * @return This {@link Builder} for method chaining.
818          */
819         public Builder setDatabase(final String database) {
820             if (database == null) {
821                 myDatabase = ADMIN_DB;
822             }
823             else {
824                 myDatabase = database;
825             }
826             return this;
827         }
828 
829         /**
830          * Sets the value of the file containing the full credentials.
831          * 
832          * @param file
833          *            The new value for the file containing the full
834          *            credentials.
835          * @return This {@link Builder} for method chaining.
836          */
837         public Builder setFile(final File file) {
838             myFile = file;
839             return this;
840         }
841 
842         /**
843          * Sets the value of the password for the credential set.
844          * 
845          * @param password
846          *            The new value for the password for the credential set.
847          * @return This {@link Builder} for method chaining.
848          */
849         public Builder setPassword(final char[] password) {
850             Arrays.fill(myPassword, '\u0000');
851 
852             if (password == null) {
853                 myPassword = NO_PASSWORD;
854             }
855             else {
856                 myPassword = password.clone();
857             }
858             return this;
859         }
860 
861         /**
862          * Sets the value of the user name for the credential set.
863          * 
864          * @param userName
865          *            The new value for the user name for the credential set.
866          * @return This {@link Builder} for method chaining.
867          */
868         public Builder setUserName(final String userName) {
869             myUserName = userName;
870             return this;
871         }
872 
873         /**
874          * Sets the value of the user name for the credential set.
875          * <p>
876          * This method delegates to {@link #setUserName(String)}.
877          * </p>
878          * 
879          * @param userName
880          *            The new value for the user name for the credential set.
881          * @return This {@link Builder} for method chaining.
882          */
883         public Builder userName(final String userName) {
884             return setUserName(userName);
885         }
886 
887         /**
888          * Sets the value of the authentication type or mode that the credential
889          * should be used with to x.509 client certificates exchanged via the
890          * TLS connection.
891          * <p>
892          * This method delegates to {@link #setAuthenticationType(String)
893          * setAuthenticationType(X509)}.
894          * </p>
895          * <p>
896          * <em>Note:</em> Use of x.509 for authentication requires the driver's
897          * extensions. See the <a href=
898          * "http://www.allanbank.com/mongodb-async-driver/userguide/authentication/tls.html"
899          * > TLS Usage Guide</a> for details.
900          * </p>
901          * 
902          * @return This {@link Builder} for method chaining.
903          * 
904          * @see <a
905          *      href="http://www.allanbank.com/mongodb-async-driver/userguide/authentication/tls.html">TLS/SSL
906          *      Usage Guide</a>
907          * @see <a
908          *      href="http://www.allanbank.com/mongodb-async-driver/userguide/authentication/x509.html">x.509
909          *      Authentication Usage Guide</a>
910          */
911         public Builder x509() {
912             return setAuthenticationType(X509);
913         }
914 
915         /**
916          * Sets the {@link #userName(String) user name} to that of the x.509
917          * certificate subject name and then sets the value of the
918          * authentication type or mode that the credential should be used with
919          * to x.509 client certificates exchanged via the TLS connection.
920          * <p>
921          * This method delegates to {@link #userName(String)
922          * userName(cert.getSubjectX500Principal().toString())}.{@link #x509()
923          * x509()}.
924          * </p>
925          * <p>
926          * <em>Note:</em> Use of x.509 for authentication requires the driver's
927          * extensions. See the <a href=
928          * "http://www.allanbank.com/mongodb-async-driver/userguide/authentication/tls.html"
929          * > TLS Usage Guide</a> for details.
930          * </p>
931          * 
932          * @param cert
933          *            The client's certificate containing the client subject
934          *            name.
935          * @return This {@link Builder} for method chaining.
936          * 
937          * @see <a
938          *      href="http://www.allanbank.com/mongodb-async-driver/userguide/authentication/tls.html">TLS/SSL
939          *      Usage Guide</a>
940          * @see <a
941          *      href="http://www.allanbank.com/mongodb-async-driver/userguide/authentication/x509.html">x.509
942          *      Authentication Usage Guide</a>
943          */
944         public Builder x509(final X509Certificate cert) {
945             return userName(cert.getSubjectX500Principal().toString()).x509();
946         }
947     }
948 }