docs: @Override
      @SuppressWarnings("unchecked")
      public boolean login() throws LoginException {
          if (isAlreadyProcessed()) {
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                  Tr.debug(tc, "Already processed by other login module, abstaining.");
              }
              return false;
          }
          customProperties = (Hashtable) sharedState.get(AttributeNameConstants.WSCREDENTIAL_PROPERTIES_KEY);
          if (customProperties == null && subject != null) {
              SubjectHelper subjectHelper = new SubjectHelper();
              customProperties = subjectHelper.getHashtableFromSubject(subject, hashtableLoginProperties);
              if (customProperties != null) {
                  customPropertiesFromSubject = true;
                  sharedState.put(AttributeNameConstants.WSCREDENTIAL_PROPERTIES_KEY, customProperties);
              }
          }
  
          // We do not have a Hashtable, abstain.
          if (customProperties == null) {
              if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
                  Tr.debug(tc, "No Hashtable could be found, abstaining.");
              }
              return false;
          }
  
          customCacheKey = getCustomCacheKey(customProperties);
          customRealm = (String) customProperties.get(AttributeNameConstants.WSCREDENTIAL_REALM);
          internalAuthProvider = (String) customProperties.get(AuthenticationConstants.INTERNAL_AUTH_PROVIDER);
  
          String uniqueId = (String) customProperties.get(AttributeNameConstants.WSCREDENTIAL_UNIQUEID);
          String securityName = (String) customProperties.get(AttributeNameConstants.WSCREDENTIAL_SECURITYNAME);
          String userId = (String) customProperties.get(AttributeNameConstants.WSCREDENTIAL_USERID);
          String password = (String) customProperties.get(AttributeNameConstants.WSCREDENTIAL_PASSWORD);
  
          if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
              if (userId != null && uniqueId != null && securityName != null) {
                  Tr.debug(tc, "The userId is set in addition to uniqueId and securityName. Only the uniqueId and securityName will be used to create the subject.");
              }
          }
  
          if (userId != null && password != null) {
              return handleUserIdAndPassword(userId, password);
          } else if (uniqueId != null && securityName != null) {
              return handleUniquedIdAndSecurityName(uniqueId, securityName, customProperties);
          } else if (userId != null && allowLoginWithIdOnly(customProperties)) {
              return handleUserId(userId);
          }
  
          if (TraceComponent.isAnyTracingEnabled() && tc.isDebugEnabled()) {
              Tr.debug(tc, "Not enough information in Hashtable to continue, abstaining.");
          }
          return false;
      }