docs: @FFDCIgnore(InvocationTargetException.class)
      Object getDB(String databaseName) throws Exception {
          final boolean trace = TraceComponent.isAnyTracingEnabled();
  
          lock.readLock().lock();
          try {
              if (mongoClient == null) {
                  // Switch to write lock for lazy initialization
                  lock.readLock().unlock();
                  lock.writeLock().lock();
                  try {
                      if (mongoClient == null)
                          init();
                  } finally {
                      // Downgrade to read lock for rest of method
                      lock.readLock().lock();
                      lock.writeLock().unlock();
                  }
              }
  
              Object db = MongoClient_getDB.invoke(mongoClient, databaseName);
  
              // authentication
              String user = (String) props.get(USER);
              if (user != null) {
                  if ((Boolean) DB_isAuthenticated.invoke(db)) {
                      if (trace && tc.isDebugEnabled())
                          Tr.debug(this, tc, "already authenticated");
                  } else {
                      if (trace && tc.isDebugEnabled())
                          Tr.debug(this, tc, "authenticate as: " + user);
                      SerializableProtectedString password = (SerializableProtectedString) props.get(PASSWORD);
                      String pwdStr = password == null ? null : String.valueOf(password.getChars());
                      pwdStr = PasswordUtil.getCryptoAlgorithm(pwdStr) == null ? pwdStr : PasswordUtil.decode(pwdStr);
                      char[] pwdChars = pwdStr == null ? null : pwdStr.toCharArray();
                      try {
                          if (!(Boolean) DB_authenticate.invoke(db, user, pwdChars))
                              if ((Boolean) DB_isAuthenticated.invoke(db)) {
                                  if (trace && tc.isDebugEnabled())
                                      Tr.debug(this, tc, "another thread must have authenticated first");
                              } else
                                  throw new IllegalArgumentException(Tr.formatMessage(tc, "CWKKD0012.authentication.error", MONGO, id, databaseName));
                      } catch (InvocationTargetException x) {
                          // If already authenticated, Mongo raises:
                          // IllegalStateException: can't authenticate twice on the same database
                          // Maybe another thread did the authentication right after we checked, so check again.
                          Throwable cause = x.getCause();
                          if (cause instanceof IllegalStateException && (Boolean) DB_isAuthenticated.invoke(db)) {
                              if (trace && tc.isDebugEnabled())
                                  Tr.debug(this, tc, "another thread must have authenticated first", cause);
                          } else
                              throw cause;
                      }
                  }
              } else if (useCertAuth) {
                  // If we specified a certificate we will already have used the client constructor that
                  // specified the credential so if we have got to here we are already authenticated and
                  // JIT should remove this so it will not be an overhead.
              }
              return db;
          } catch (Throwable x) {
              // rethrowing the exception allows it to be captured in FFDC and traced automatically
              x = x instanceof InvocationTargetException ? x.getCause() : x;
              if (x instanceof Exception)
                  throw (Exception) x;
              else if (x instanceof Error)
                  throw (Error) x;
              else
                  throw new RuntimeException(x);
          } finally {
              lock.readLock().unlock();
          }
      }