/**
   * Return <code>true</code> if the specified Principal has the specified security role, within the
   * context of this Realm; otherwise return <code>false</code>.
   *
   * <p>Since the Principal, in the JaasSecurityManager, has been stored in its cache using the
   * JOSSO Single Sign-On Session Identifier Principal (see isValid method), when roles are checked
   * , the Principal to be submitted to the overriden operation is not the user principal but the
   * JOSSO Session Id Principal.
   *
   * @param principal Principal for whom the role is to be checked
   * @param role Security role to be checked
   */
  public boolean hasRole(Principal principal, String role) {
    boolean hasRole = false;

    try {
      Context securityCtx = null;
      securityCtx = prepareENC();

      if (securityCtx == null) {
        logger.error("No security context for authenticate(String, String)");
        return false;
      }

      logger.debug("hasRole(" + principal + "," + role + ")");

      // Get the JBoss security manager from the ENC context
      SubjectSecurityManager securityMgr =
          (SubjectSecurityManager) securityCtx.lookup("securityMgr");
      if (!isSSODomain(securityMgr.getSecurityDomain())) {
        // This is not a SSO Security domain, let JBoss realm handle this ...
        return super.hasRole(principal, role);
      }

      Subject activeSubject = securityMgr.getActiveSubject();

      logger.debug("Authenticated Subject: " + activeSubject);

      CatalinaSSOUser ssoUser = CatalinaSSOUser.newInstance(this, activeSubject);
      hasRole = super.hasRole(ssoUser, role);

    } catch (NamingException e) {
      principal = null;
      logger.error("Error during authenticate", e);
    }

    return hasRole;
  }
  /**
   * Return the Principal associated with the specified username and credentials, if there is one;
   * otherwise return null.
   *
   * <p>The method was completely rewritten since the overriden operation, on succesfull
   * authentication, sets as the authenticated Principal a SimplePrincipal instantiated using the
   * provided username. The problem is that in JOSSO the username is a SSO Session Id, not a
   * username. So we need to set the SSOUser returned by the Gateway as the authenticatd Principal.
   * Since the JaasSecurityManager caches the authenticated user using the Principal referring to a
   * JOSSO Session Id, we will need to map, for example when roles are checked against the realm, a
   * user Principal back to its JOSSO Session Identifier Principal. This way the the user and its
   * roles can be retrieved correctly by the JaasSecurityManager.
   *
   * @param username Username of the Principal to look up
   * @param credentials Password or other credentials to use in authenticating this username
   */
  public Principal authenticate(String username, String credentials) {

    logger.debug("Begin authenticate, username="******"No security context for authenticate(String, String)");
        return null;
      }

      // Get the JBoss security manager from the ENC context
      SubjectSecurityManager securityMgr =
          (SubjectSecurityManager) securityCtx.lookup("securityMgr");
      if (!isSSODomain(securityMgr.getSecurityDomain())) {
        // This is not a SSO Security domain, let JBoss realm handle this ...
        return super.authenticate(username, credentials);
      }

      principal = new SimplePrincipal(username);
      char[] passwordChars = null;
      if (credentials != null) passwordChars = credentials.toCharArray();

      String requester = "";
      // Check for nulls ?
      SSOAgentRequest request = AbstractSSOAgent._currentRequest.get();
      if (request == null)
        logger.error(
            "No SSO Agent request found in thread local variable, can't identify requester!");

      SSOAgent agent = Lookup.getInstance().lookupSSOAgent();
      SSOIdentityManagerService im = request.getConfig(agent).getIdentityManagerService();
      if (im == null) im = agent.getSSOIdentityManager();

      requester = request.getRequester();
      ssoUser = im.findUserInSession(requester, username);

      if (ssoUser != null) {
        logger.debug("User: "******" is authenticated");

        Subject subject = new Subject();
        subject.getPrincipals().add(ssoUser);
        logger.warn("WARN Cannot identify requester!");
        SSORole[] ssoRolePrincipals = im.findRolesBySSOSessionId(requester, username);
        Group targetGrp = new BaseRoleImpl("Roles");
        for (int i = 0; i < ssoRolePrincipals.length; i++) {
          subject.getPrincipals().add(ssoRolePrincipals[i]);
          targetGrp.addMember(ssoRolePrincipals[i]); // Add user role to "Roles" group
        }
        // Add the "Roles" group to the Subject so that JBoss can fetch user roles.
        subject.getPrincipals().add(targetGrp);

        logger.debug("Authenticated Subject: " + subject);

        // Make the cache aware of the user-session association so that
        // it can handle correctly cache entry lookups.
        // _cachePolicy.attachSessionToUser(principal, ssoUser);

        // Instead of associating the Principal used for authenticating (which is a
        // session id), sets the authenticated principal to the SSOUser part of the
        // Subject returned by the Gateway.
        JBossSecurityAssociationActions.setPrincipalInfo(ssoUser, passwordChars, subject);

        // Get the CallerPrincipal mapping
        RealmMapping rm = (RealmMapping) securityCtx.lookup("realmMapping");
        Principal oldPrincipal = ssoUser;
        principal = rm.getPrincipal(oldPrincipal);
        logger.debug("Mapped from input principal: " + oldPrincipal + " to: " + principal);
        if (!principal.equals(oldPrincipal)) {
          _userPrincipalMap.put(principal, oldPrincipal);
        }

      } else {
        principal = null;
        logger.debug("User: "******" is NOT authenticated");
      }
    } catch (NamingException e) {
      principal = null;
      logger.error("Error during authenticate", e);
    } catch (SSOIdentityException e) {
      // Ignore this ... (user does not exist for this session)
      if (logger.isDebugEnabled()) {
        logger.debug(e.getMessage());
      }
      principal = null;
    } catch (Exception e) {
      logger.error("Session authentication failed : " + username, e);
      throw new RuntimeException("Fatal error authenticating session : " + e);
    }
    logger.debug("End authenticate, principal=" + ssoUser);
    return ssoUser;
  }