Coverage Report - com.allanbank.mongodb.Credential
 
Classes in this File Line Coverage Branch Coverage Complexity
Credential
94%
91/96
96%
56/58
1.886
Credential$Builder
96%
49/51
83%
5/6
1.886
 
 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  1
     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  1
         KERBEROS = "com.allanbank.mongodb.extensions.authentication.KerberosAuthenticator";
 129  1
         MONGODB_CR = MongoDbAuthenticator.class.getName();
 130  1
         PLAIN_SASL = "com.allanbank.mongodb.extensions.authentication.PlainSaslAuthenticator";
 131  1
         X509 = "com.allanbank.mongodb.extensions.authentication.X509Authenticator";
 132  1
     }
 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  2780
         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  2781
     public Credential(final Builder builder) {
 173  2781
         myUserName = builder.myUserName;
 174  2781
         myDatabase = builder.myDatabase;
 175  2781
         myFile = builder.myFile;
 176  2781
         myAuthenticationType = builder.myAuthenticationType;
 177  2781
         myAuthenticator = builder.myAuthenticator;
 178  2781
         myPassword = builder.myPassword.clone();
 179  2781
         myOptions = Collections.unmodifiableMap(new HashMap<String, String>(
 180  
                 builder.myOptions));
 181  2781
     }
 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  28
         if (myAuthenticator == null) {
 192  
             try {
 193  2
                 loadAuthenticator();
 194  
             }
 195  1
             catch (final ClassNotFoundException e) {
 196  1
                 throw new MongoDbAuthenticationException(e);
 197  
             }
 198  0
             catch (final InstantiationException e) {
 199  0
                 throw new MongoDbAuthenticationException(e);
 200  
             }
 201  0
             catch (final IllegalAccessException e) {
 202  0
                 throw new MongoDbAuthenticationException(e);
 203  1
             }
 204  
         }
 205  
 
 206  27
         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  907896
         boolean result = false;
 218  907896
         if (this == object) {
 219  1348
             result = true;
 220  
         }
 221  906548
         else if ((object != null) && (getClass() == object.getClass())) {
 222  903860
             final Credential other = (Credential) object;
 223  
 
 224  903860
             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  907896
         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  48
         return myAuthenticationType;
 244  
     }
 245  
 
 246  
     /**
 247  
      * Returns the authenticator value.
 248  
      * 
 249  
      * @return The authenticator value.
 250  
      */
 251  
     public Authenticator getAuthenticator() {
 252  3
         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  121
         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  0
         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  3
         final String value = myOptions.get(optionName);
 287  3
         if (value != null) {
 288  2
             return Boolean.parseBoolean(value);
 289  
         }
 290  1
         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  3
         final String value = myOptions.get(optionName);
 305  3
         if (value != null) {
 306  
             try {
 307  2
                 return Integer.parseInt(value);
 308  
             }
 309  1
             catch (final NumberFormatException nfe) {
 310  1
                 return defaultValue;
 311  
             }
 312  
         }
 313  1
         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  3
         String value = myOptions.get(optionName);
 327  3
         if (value == null) {
 328  1
             value = defaultValue;
 329  
         }
 330  
 
 331  3
         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  46
         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  105
         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  1807680
         int result = 1;
 364  
 
 365  1807680
         result = (31 * result)
 366  
                 + ((myAuthenticationType == null) ? 0 : myAuthenticationType
 367  
                         .hashCode());
 368  1807680
         result = (31 * result)
 369  
                 + ((myDatabase == null) ? 0 : myDatabase.hashCode());
 370  1807680
         result = (31 * result) + myOptions.hashCode();
 371  1807680
         result = (31 * result) + Arrays.hashCode(myPassword);
 372  1807680
         result = (31 * result)
 373  
                 + ((myUserName == null) ? 0 : myUserName.hashCode());
 374  1807680
         result = (31 * result) + ((myFile == null) ? 0 : myFile.hashCode());
 375  
 
 376  1807680
         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  2
         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  10
         final StringBuilder builder = new StringBuilder();
 398  10
         builder.append("{ username : '");
 399  10
         builder.append(myUserName);
 400  10
         builder.append("', database : '");
 401  10
         builder.append(myDatabase);
 402  10
         if (myFile != null) {
 403  5
             builder.append("', file : '");
 404  5
             builder.append(myFile.getName());
 405  
         }
 406  10
         builder.append("', password : '<redacted>', type: '");
 407  10
         if (KERBEROS.equals(myAuthenticationType)) {
 408  2
             builder.append("KERBEROS");
 409  
         }
 410  8
         else if (PLAIN_SASL.equals(myAuthenticationType)) {
 411  3
             builder.append("PLAIN SASL");
 412  
         }
 413  5
         else if (X509.equals(myAuthenticationType)) {
 414  1
             builder.append("x.509");
 415  
         }
 416  4
         else if (MONGODB_CR.equals(myAuthenticationType)) {
 417  3
             builder.append("MONGODB-CR");
 418  
         }
 419  1
         else if (myAuthenticationType != null) {
 420  1
             builder.append(myAuthenticationType);
 421  
         }
 422  
 
 423  10
         for (final Map.Entry<String, String> option : myOptions.entrySet()) {
 424  1
             builder.append("', '");
 425  1
             builder.append(option.getKey());
 426  1
             builder.append("': '");
 427  1
             builder.append(option.getValue());
 428  1
         }
 429  
 
 430  10
         builder.append("' }");
 431  
 
 432  10
         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  46
         if (myAuthenticator == null) {
 448  45
             myAuthenticator = (Authenticator) Class.forName(
 449  
                     getAuthenticationType()).newInstance();
 450  
         }
 451  45
     }
 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  1207672
         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  1
         in.defaultReadObject();
 480  1
         myAuthenticator = null;
 481  1
     }
 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  2780
         public Builder() {
 517  2780
             myOptions = new HashMap<String, String>();
 518  2780
             reset();
 519  2780
         }
 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  1
             myOptions.put(optionName, String.valueOf(optionValue));
 533  
 
 534  1
             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  1
             myOptions.put(optionName, String.valueOf(optionValue));
 548  
 
 549  1
             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  1159
             myOptions.put(optionName, optionValue);
 564  
 
 565  1159
             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  2723
             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  3
             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  2781
             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  2764
             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  2693
             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  6
             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  1
             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  17
             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  1
             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  2771
             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  3
             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  2780
             if (myPassword != null) {
 770  0
                 Arrays.fill(myPassword, '\u0000');
 771  
             }
 772  
 
 773  2780
             myAuthenticationType = MONGODB_CR;
 774  2780
             myAuthenticator = null;
 775  2780
             myDatabase = ADMIN_DB;
 776  2780
             myFile = null;
 777  2780
             myPassword = NO_PASSWORD;
 778  2780
             myUserName = null;
 779  2780
             myOptions.clear();
 780  
 
 781  2780
             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  2754
             myAuthenticationType = authenticationType;
 795  2754
             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  3
             myAuthenticator = authenticator;
 808  3
             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  2765
             if (database == null) {
 821  678
                 myDatabase = ADMIN_DB;
 822  
             }
 823  
             else {
 824  2087
                 myDatabase = database;
 825  
             }
 826  2765
             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  2693
             myFile = file;
 839  2693
             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  2780
             Arrays.fill(myPassword, '\u0000');
 851  
 
 852  2780
             if (password == null) {
 853  384
                 myPassword = NO_PASSWORD;
 854  
             }
 855  
             else {
 856  2396
                 myPassword = password.clone();
 857  
             }
 858  2780
             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  2780
             myUserName = userName;
 870  2780
             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  2780
             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  3
             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  0
             return userName(cert.getSubjectX500Principal().toString()).x509();
 946  
         }
 947  
     }
 948  
 }