/*
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
 *
 * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved
 *
 * The contents of this file are subject to the terms
 * of the Common Development and Distribution License
 * (the License). You may not use this file except in
 * compliance with the License.
 *
 * You can obtain a copy of the License at
 * https://opensso.dev.java.net/public/CDDLv1.0.html or
 * opensso/legal/CDDLv1.0.txt
 * See the License for the specific language governing
 * permission and limitations under the License.
 *
 * When distributing Covered Code, include this CDDL
 * Header Notice in each file and include the License file
 * at opensso/legal/CDDLv1.0.txt.
 * If applicable, add the following below the CDDL Header,
 * with the fields enclosed by brackets [] replaced by
 * your own identifying information:
 * "Portions Copyrighted [year] [name of copyright owner]"
 *
 * $Id: FSAssertionArtifactHandler.java,v 1.14 2009/11/03 00:49:49 madan_ranganath Exp $
 *
 * Portions Copyrighted 2015-2016 ForgeRock AS.
 */

package com.sun.identity.federation.services.fednsso;

import static org.forgerock.openam.utils.Time.*;

import com.sun.identity.common.PeriodicGroupRunnable;
import com.sun.identity.common.ScheduleableGroupAction;
import com.sun.identity.common.SystemTimerPool;
import com.sun.identity.common.SystemConfigurationUtil;
import com.sun.identity.common.TaskRunnable;
import com.sun.identity.common.TimerPool;
import com.sun.identity.federation.accountmgmt.FSAccountFedInfo;
import com.sun.identity.federation.accountmgmt.FSAccountFedInfoKey;
import com.sun.identity.federation.accountmgmt.FSAccountManager;
import com.sun.identity.federation.accountmgmt.FSAccountMgmtException;
import com.sun.identity.federation.common.FSException;
import com.sun.identity.federation.common.FSUtils;
import com.sun.identity.federation.common.IFSConstants;
import com.sun.identity.federation.common.LogUtil;
import com.sun.identity.federation.jaxb.entityconfig.BaseConfigType;
import com.sun.identity.federation.key.KeyUtil;
import com.sun.identity.federation.message.FSAssertion;
import com.sun.identity.federation.message.FSAuthenticationStatement;
import com.sun.identity.federation.message.FSAuthnRequest;
import com.sun.identity.federation.message.FSAuthnResponse;
import com.sun.identity.federation.message.FSResponse;
import com.sun.identity.federation.message.FSSubject;
import com.sun.identity.federation.message.common.AuthnContext;
import com.sun.identity.federation.meta.IDFFMetaException;
import com.sun.identity.federation.meta.IDFFMetaManager;
import com.sun.identity.federation.meta.IDFFMetaUtils;
import com.sun.identity.federation.plugins.FederationSPAdapter;
import com.sun.identity.federation.services.FSSPAuthenticationContextInfo;
import com.sun.identity.federation.services.FSAttributeMapper;
import com.sun.identity.federation.services.FSRealmAttributeMapper;
import com.sun.identity.federation.services.FSServiceManager;
import com.sun.identity.federation.services.FSSession;
import com.sun.identity.federation.services.FSSessionManager;
import com.sun.identity.federation.services.FSSessionPartner;
import com.sun.identity.federation.services.logout.FSTokenListener;
import com.sun.identity.federation.services.registration.FSNameRegistrationHandler;
import com.sun.identity.federation.services.util.FSServiceUtils;
import com.sun.identity.liberty.ws.meta.jaxb.IDPDescriptorType;
import com.sun.identity.liberty.ws.meta.jaxb.SPDescriptorType;
import com.sun.identity.plugin.session.SessionException;
import com.sun.identity.plugin.session.SessionManager;
import com.sun.identity.plugin.session.SessionProvider;
import com.sun.identity.saml.assertion.Attribute;
import com.sun.identity.saml.assertion.AttributeStatement;
import com.sun.identity.saml.assertion.AudienceRestrictionCondition;
import com.sun.identity.saml.assertion.Conditions;
import com.sun.identity.saml.assertion.NameIdentifier;
import com.sun.identity.saml.assertion.Statement;
import com.sun.identity.saml.assertion.Subject;
import com.sun.identity.saml.assertion.SubjectConfirmation;
import com.sun.identity.saml.common.SAMLConstants;
import com.sun.identity.saml.common.SAMLException;
import com.sun.identity.saml.common.SAMLResponderException;
import com.sun.identity.saml.common.SAMLServiceManager;
import com.sun.identity.saml.protocol.Response;
import com.sun.identity.saml.servlet.POSTCleanUpRunnable;
import com.sun.identity.saml.xmlsig.XMLSignatureManager;
import com.sun.identity.shared.xml.XMLUtils;
import com.sun.identity.shared.encode.CookieUtils;
import com.sun.identity.shared.DateUtils;
import java.io.IOException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.logging.Level;
import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

/**
 * Handler that runs on <code>SP</code> side to receive and process 
 * <code>AuthnResponse</code>.
 */
public class FSAssertionArtifactHandler {
    private String idpSessionIndex = null;
    private Date reAuthnOnOrAfterDate = null; // TODO: not used currently
    private AuthnContext authnContextStmt = null;

    protected HttpServletRequest request = null;
    protected HttpServletResponse response = null;
    protected IDPDescriptorType idpDescriptor = null;
    protected String idpEntityId = null;
    protected FSAuthnRequest authnRequest = null;
    protected String relayState= null;
    
    protected static Map idTimeMap = Collections.synchronizedMap(new HashMap());
    private static TaskRunnable cGoThrough = null;
    private static TaskRunnable cPeriodic = null;
    protected boolean doFederate = false;
    protected String nameIDPolicy = null;
    
    protected AttributeStatement bootStrapStatement = null;
    protected AttributeStatement _autoFedStatement = null;
    protected Map autoFedSearchMap = null;
    protected List securityAssertions = null;
    protected Object ssoToken = null;
    protected FSAuthnResponse authnResponse = null;
    protected Element samlResponseElt = null;
    protected List attrStatements = new ArrayList();
    protected SPDescriptorType hostDesc = null;
    protected BaseConfigType hostConfig = null;
    protected String realm = null;
    protected String hostEntityId = null;
    protected String hostMetaAlias = null;
    protected static String ANONYMOUS_PRINCIPAL = "anonymous";
    protected FSAttributeMapper attributeMapper = null;
    protected FSRealmAttributeMapper realmAttributeMapper = null;
    protected FSResponse samlResponse = null;
    
    static {
        long period = ((Integer) SAMLServiceManager.getAttribute(
            SAMLConstants.CLEANUP_INTERVAL_NAME)).intValue() * 1000;
        cGoThrough = new POSTCleanUpRunnable(period, idTimeMap);
        TimerPool timerPool = SystemTimerPool.getTimerPool();
        timerPool.schedule(cGoThrough, new Date(((currentTimeMillis()
                + period) / 1000) * 1000));
        ScheduleableGroupAction periodicAction = new ScheduleableGroupAction() {
            public void doGroupAction(Object obj) {
                idTimeMap.remove(obj);
            }
        };
        cPeriodic = new PeriodicGroupRunnable(periodicAction, period, 180000,
            true);
        timerPool.schedule(cPeriodic, new Date(((currentTimeMillis() +
                period) / 1000) * 1000));
    }
    
    /**
     * Sets hosted SP entity ID.
     * @param entityId hosted SP's entity ID to be set
     */
    public void setHostEntityId(String entityId) {
        hostEntityId = entityId;
    }
 
    /**
     * Sets hosted SP meta descriptor.
     * @param desc SP's meta descriptor to be set.
     * @see #getHostEntityId()
     */
    public void setHostDescriptor(SPDescriptorType desc) {
        hostDesc = desc;
    }

    /**
     * Sets hosted SP extended meta config.
     * @param config SP's extended meta to be set.
     */
    public void setHostDescriptorConfig(BaseConfigType config) {
        hostConfig = config;
    }

    /**
     * Sets hosted SP's meta alias.
     * @param metaAlias SP's meta alias to be set
     */
    public void setMetaAlias(String metaAlias) {
        hostMetaAlias = metaAlias;
    }
    /**
     * Gets hosted SP's Entity ID.
     * @return hosted entity id.
     * @see #setHostEntityId(String)
     */
    public String getHostEntityId() {
        return hostEntityId;
    }
    
    /**
     * Gets the realm under which the entity resides.
     * @return the realm under which the entity resides.
     * @see #setRealm(String)
     */
    public String getRealm() {
        return realm;
    }

    /**
     * Sets the realm under which the entity resides.
     * @param realm The realm under which the entity resides.
     * @see #getRealm()
     */
    public void setRealm(String realm) {
        this.realm = realm;
    }

    /**
     * Gets <code>FSAuthnRequest</code> object.
     * @return <code>FSAuthnRequest</code> object
     * @see #setAuthnRequest(FSAuthnRequest)
     */
    public FSAuthnRequest getAuthnRequest() {
        return authnRequest;
    }

    /**
     * Sets <code>FSAuthnRequest</code> object.
     * @param authnRequest <code>FSAuthnRequest</code> object to be set.
     * @see #getAuthnRequest()
     */
    public void setAuthnRequest(FSAuthnRequest authnRequest) {
        this.authnRequest = authnRequest;
    }
    
    /**
     * Default constructor.
     */
    protected FSAssertionArtifactHandler(){
    }
    
    /**
     * Constructs a <code>FSAssertionArtifactHandler</code> object.
     * @param request <code>HttpServletRequest</code> object.
     * @param response <code>HttpServletResponse</code> object
     * @param idpDescriptor <code>IDP</code> provider descriptor
     * @param idpEntityId entity ID of the <code>IDP</code>
     * @param doFederate a flag indicating if it is a federation request
     * @param nameIDPolicy <code>nameIDPolicy</code> used
     * @param relayState <code>RelayState</code> url
     */
    public FSAssertionArtifactHandler(
        HttpServletRequest request, 
        HttpServletResponse response, 
        IDPDescriptorType idpDescriptor, 
        String idpEntityId,
        boolean doFederate,
        String nameIDPolicy,
        String relayState
    )
    {
        this.request = request;
        this.response = response;
        this.relayState = relayState;
        this.idpDescriptor = idpDescriptor;
        this.idpEntityId = idpEntityId;
        
        this.doFederate = doFederate;
        this.nameIDPolicy = nameIDPolicy;
    }
    
    /**
     * Constructs a <code>FSAssertionArtifactHandler</code> object.
     * @param request <code>HttpServletRequest</code> object.
     * @param response <code>HttpServletResponse</code> object
     * @param idpDescriptor <code>IDP</code> provider descriptor
     * @param idpEntityId entity ID of the <code>IDP</code>
     * @param authnRequest <code>FSAuthnRequest</code> from soap
     * @param doFederate a flag indicating if it is a federation request
     * @param relayState <code>RelayState</code> url
     */
    public FSAssertionArtifactHandler(
        HttpServletRequest request, 
        HttpServletResponse response, 
        IDPDescriptorType idpDescriptor, 
        String idpEntityId,
        FSAuthnRequest authnRequest, 
        boolean doFederate,
        String relayState
    )
    {
        this.request = request;
        this.response = response;
        this.relayState = relayState;
        this.idpDescriptor = idpDescriptor;
        this.idpEntityId = idpEntityId;
        if (authnRequest != null) {
            this.authnRequest = authnRequest;            
            this.nameIDPolicy = authnRequest.getNameIDPolicy();
        }
        
        this.doFederate = doFederate;
    }
    
    /**
     * Processes <code>FSAuthnResponse</code>.
     * @param authnResponse <code>FSAuthnResponse</code> objec to be processed
     */
    public void processAuthnResponse(FSAuthnResponse authnResponse) {
        FSUtils.debug.message(
            "FSAssertionArtifactHandler.ProcessAuthnResponse: Called");
        this.authnResponse = authnResponse;
        // Call SP adapter SPI
        FederationSPAdapter spAdapter = FSServiceUtils.getSPAdapter(
            hostEntityId, hostConfig);
        if (spAdapter != null) {
            if (FSUtils.debug.messageEnabled()) {
                FSUtils.debug.message("FSAssertionArtifactHandler, POST"
                    + " Invokde spAdapter.preSSOFederationProcess");
            }
            try {
                spAdapter.preSSOFederationProcess(hostEntityId,
                    request, response, authnRequest, authnResponse, null);
            } catch (Exception e) {
                // log run time exception in Adapter
                // implementation, continue
                FSUtils.debug.error("FSAssertionArtifactHandler" +
                    " SPAdapter.preSSOFederationSuccess", e);
            }
        }
        String baseURL = FSServiceUtils.getBaseURL(request);
        String framedLoginPageURL = FSServiceUtils.getCommonLoginPageURL(
            hostMetaAlias, 
            authnRequest.getRelayState(),
            null,
            request,
            baseURL);
        
        this.relayState = authnRequest.getRelayState();
        if ((this.relayState == null) || (this.relayState.trim().length() == 0))
        {
            this.relayState =
                IDFFMetaUtils.getFirstAttributeValueFromConfig(
                    hostConfig, IFSConstants.PROVIDER_HOME_PAGE_URL);
            if ((this.relayState == null) || 
                (this.relayState.trim().length() == 0))
            {
                this.relayState = 
                    baseURL + IFSConstants.SP_DEFAULT_RELAY_STATE;
            }
        }
        try {
            if (authnResponse == null) {
                String[] data = 
                    { FSUtils.bundle.getString("missingAuthnResponse") };
                LogUtil.error(Level.INFO,LogUtil.MISSING_AUTHN_RESPONSE,data,
                    ssoToken);
                FSUtils.debug.error("FSAssertionArtifactHandler."
                    + "processAuthnResponse: " 
                    + FSUtils.bundle.getString("missingAuthnResponse")
                    + " AuthnRequest Processing Failed at the IDP "
                    + "Redirecting to the Framed Login Page");
                response.sendRedirect(framedLoginPageURL);
                return;
            }
            if (FSUtils.debug.messageEnabled()) {
                FSUtils.debug.message(
                    "FSAssertionArtifactHandler.doPost:Received " +
                    authnResponse.toXMLString());
            }
            
            boolean valid = verifyResponseStatus(authnResponse);
            if (!valid) {
                FSSessionManager sessionManager =
                    FSSessionManager.getInstance(hostMetaAlias);
                // clean request map
                String inResponseTo = authnResponse.getInResponseTo();
                sessionManager.removeAuthnRequest(inResponseTo);
                String[] data = 
                    { authnResponse.toXMLString() };
                LogUtil.error(Level.INFO,LogUtil.INVALID_AUTHN_RESPONSE,data,
                    ssoToken);
                FSUtils.debug.warning("FSAssertionArtifactHandler."
                    + " processAuthnResponse: "
                    + FSUtils.bundle.getString("invalidResponse")
                    + " AuthnRequest Processing Failed at the IDP"
                    + " Redirecting to the Framed Login Page");
                if ((spAdapter == null) || !(spAdapter.postSSOFederationFailure(
                    hostEntityId, request, response, authnRequest,
                    authnResponse, null,
                    FederationSPAdapter.INVALID_AUTHN_RESPONSE)))
                {
                   response.sendRedirect(framedLoginPageURL);
                }
                return;
            }
            
            // check Assertion
            List assertions = authnResponse.getAssertion();
            FSSubject validSubject =(FSSubject)validateAssertions(assertions);
            if (validSubject == null) {
                String[] data = { FSUtils.bundle.getString("invalidAssertion")};
                LogUtil.error(Level.INFO,LogUtil.INVALID_ASSERTION,data,
                    ssoToken);
                FSUtils.debug.error("FSAssertionArtifactHandler."
                    + "processAuthnResponse: " 
                    + FSUtils.bundle.getString("InvalidResponse")
                    + " AuthnRequest Processing Failed at the IDP"
                    + " Redirecting to the Framed Login Page");
                response.sendRedirect(framedLoginPageURL);
                return;
            }
           
            FSSessionManager sessionManager = 
                FSSessionManager.getInstance(hostMetaAlias);

            if (doFederate){
                if (FSUtils.debug.messageEnabled()) {
                    FSUtils.debug.message("FSAssertionArtifactHandler." +
                        "processAuthnResponse: Initiate Account Federation");
                }
                NameIdentifier ni = validSubject.getIDPProvidedNameIdentifier();
                if (ni == null) {
                    if (FSUtils.debug.messageEnabled()) {
                        FSUtils.debug.message(
                            "FSAssertionArtifactHandler.processAuthnResponse:" +
                            " IDPProvided NameIdentifier is null");
                    }
                    ni = validSubject.getNameIdentifier();
                }
                if (ni != null){
                    int returnCode = doAccountFederation(ni);
                    if (returnCode == FederationSPAdapter.SUCCESS) {
                        if (FSUtils.debug.messageEnabled()) {
                            FSUtils.debug.message("FSAssertionArtifactHandler."
                                + "processAuthnResponse: Account federation"
                                + " successful");
                        }
                        
                        String inResponseTo = authnResponse.getInResponseTo();
                        sessionManager.removeAuthnRequest(inResponseTo);
                        sessionManager.removeLocalSessionToken(inResponseTo);
                        return;
                    } else {
                        String[] data = {FSUtils.bundle.getString(
                            "AccountFederationFailed")};
                        LogUtil.error(Level.INFO,
                                    LogUtil.ACCOUNT_FEDERATION_FAILED,
                                    data,
                                    ssoToken);
                        FSUtils.debug.error("FSAssertionArtifactHandler."
                            + "processAuthnResponse: " + 
                            FSUtils.bundle.getString("AccountFederationFailed")
                                + " AuthnRequest Processing Failed at the IDP"
                                + " Redirecting to the Framed Login Page");
                        if (spAdapter == null ||
                            !spAdapter.postSSOFederationFailure(
                                hostEntityId,
                                request, response, authnRequest,
                                authnResponse, (FSResponse)samlResponse,
                                returnCode))
                        {
                            response.sendRedirect(framedLoginPageURL);
                        }
                    }
                } else {
                    throw new FSException("missingNIofSubject", null);
                }
            } else {
                if (FSUtils.debug.messageEnabled()) {
                    FSUtils.debug.message("FSAssertionArtifactHandler."
                        + "processAuthnResponse: Initiate SingleSign-On");
                }
                //check for SPProvidedNameIdentifier
                NameIdentifier niIdp = 
                    validSubject.getIDPProvidedNameIdentifier();
                NameIdentifier ni = validSubject.getNameIdentifier();
                if (niIdp == null) {
                    if (FSUtils.debug.messageEnabled()) {
                        FSUtils.debug.message(
                            "FSAssertionArtifactHandler.processAuthnResponse:" +
                            " IDPProvided NameIdentifier is null");
                    }
                    niIdp = ni;
                }
                if ((niIdp == null) ||(ni == null)){
                    String[] data =
                        { FSUtils.bundle.getString("invalidResponse")};
                    LogUtil.error(
                        Level.INFO,LogUtil.INVALID_AUTHN_RESPONSE, data,
                        ssoToken);
                    FSUtils.debug.error("FSAssertionArtifactHandler."
                        + " processAuthnResponse: "
                        + FSUtils.bundle.getString("invalidResponse")
                        + " AuthnRequest Processing Failed at the IDP"
                        + " Redirecting to the Framed Login Page");
                    response.sendRedirect(framedLoginPageURL);
                    return;
                }
                
                String idpHandle = niIdp.getName();
                String spHandle = ni.getName();
                int handleType;
                if ((idpHandle == null) || (spHandle == null)) {
                    String[] data = 
                        { FSUtils.bundle.getString("invalidResponse")};
                    LogUtil.error(
                        Level.INFO,LogUtil.INVALID_AUTHN_RESPONSE,data,
                        ssoToken);
                    FSUtils.debug.error("FSAssertionArtifactHandler."
                        + "processAuthnResponse: "
                        + FSUtils.bundle.getString("invalidResponse")
                        + " AuthnRequest Processing Failed at the IDP"
                        + " Redirecting to the Framed Login Page");
                    response.sendRedirect(framedLoginPageURL);
                    return;
                }
                if (idpHandle.equals(spHandle)){
                    ni = niIdp;
                    handleType = IFSConstants.REMOTE_OPAQUE_HANDLE;
                } else {
                    handleType = IFSConstants.LOCAL_OPAQUE_HANDLE;
                }
                
                Map env = new HashMap();
                env.put(IFSConstants.FS_USER_PROVIDER_ENV_AUTHNRESPONSE_KEY,
                    authnResponse);
                int returnCode = 
                    doSingleSignOn(ni, handleType, niIdp, env);
                if (returnCode == FederationSPAdapter.SUCCESS){
                    if (FSUtils.debug.messageEnabled()) {
                        FSUtils.debug.message("FSAssertionArtifactHandler."
                        + "processAuthnResponse: Accountfederation successful");
                    }
                    
                    String requestID = authnResponse.getInResponseTo();
                    sessionManager.removeAuthnRequest(requestID);
                    if (isIDPProxyEnabled(requestID)) {
                        sendProxyResponse(requestID);
                        return;
                    }
                    String[] data = {this.relayState};
                    LogUtil.access(
                        Level.INFO,LogUtil.ACCESS_GRANTED_REDIRECT_TO, data,
                        ssoToken); 
                    FSUtils.debug.message(
                        "ArtifactHandler.notfederated, postSSO");
                    if (spAdapter != null) {
                        if (FSUtils.debug.messageEnabled()) {
                            FSUtils.debug.message("FSAssertionArtifactHandler,"
                                + " Invoke spAdapter.postSSOFederationSuccess");
                        }
                        try {
                            if (spAdapter.postSSOFederationSuccess(
                                    hostEntityId, request, response, ssoToken,
                                    authnRequest, authnResponse, null))
                            {
                                // return if the SP spi redirection happened
                                return;
                            }
                        } catch (Exception e) {
                            // log run time exception in Adapter
                            // implementation, continue
                            FSUtils.debug.error("FSAssertionArtifadctHandler"
                                + " SPAdapter.postSSOFederationSuccess:", e);
                        }
                    }
                    redirectToResource(this.relayState);
                    return;
                } else {
                    String[] data = { FSUtils.bundle.getString("SSOfailed") };
                    LogUtil.error(Level.INFO,LogUtil.SINGLE_SIGNON_FAILED,data,
                        ssoToken);
                    FSUtils.debug.error("FSAssertionArtifactHandler."
                        + "processAuthnResponse: "
                        + FSUtils.bundle.getString("invalidResponse")
                        + " AuthnRequest Processing Failed at the IDP"
                        + " Redirecting to the Framed Login Page");
                    if (spAdapter == null || 
                        !spAdapter.postSSOFederationFailure(
                            hostEntityId, request, response,
                            authnRequest, authnResponse, null, returnCode))
                    {
                       response.sendRedirect(framedLoginPageURL);
                    }
                    return;
                }
                
            }
        } catch(Exception e){
            FSUtils.debug.error("FSAssertionArtifactHandler."
                + "processAuthnResponse: Exception Occured: ", e);
            try {
                FSUtils.debug.error("FSAssertionArtifactHandler."
                    + "processAuthnResponse: "
                    + FSUtils.bundle.getString("invalidResponse")
                    + " AuthnRequest Processing Failed at the IDP"
                    + " Redirecting to the Framed Login Page");
                response.sendRedirect(framedLoginPageURL);
            } catch(IOException ioe){
                FSUtils.debug.error("FSAssertionArtifactHandler."
                    + "processAuthnResponse: IOException Occured: ", ioe);
                return;
            }
            return;
        }
    }
    
    protected boolean verifyResponseStatus(Response resp) {
        FSUtils.debug.message(
            "FSAssertionArtifactHandler.verifyResponseStatus: Called");
        // check status of the AuthnResponse
        if (!resp.getStatus().getStatusCode().getValue().endsWith(
            IFSConstants.STATUS_CODE_SUCCESS_NO_PREFIX)) 
        {
            FSUtils.debug.warning("FSAssertionArtifactHandler.verifyResponse: "
                + "Incorrect StatusCode value.");
            return false;
        }

        if (FSUtils.debug.messageEnabled()) {
            FSUtils.debug.message("FSAssertionArtifactHandler.verifyResponse: "
                + "StatusCode value verified.");
        }
        return true;
    }
    
    protected Subject validateAssertions(List assertions) {
        FSUtils.debug.message(
            "FSAssertionArtifactHandler.validateAssertions: Called");
        // loop to check assertions
        FSSubject subject = null;
        
        Iterator iter = assertions.iterator();
        FSAssertion assertion = null;
        String aIDString = null;
        String issuer = null;
        
        Iterator stmtIter = null;
        Statement statement = null;
        int stmtType = Statement.NOT_SUPPORTED;
        SubjectConfirmation subConf = null;
        Set confMethods = null;
        String confMethod = null;
        Date date = null;
        
        long time = currentTimeMillis() + 180000;
        while (iter.hasNext()) {
            assertion =(FSAssertion) iter.next();
            
            //check for valid AuthnRequest correspondence
            
            if (!authnRequest.getRequestID().equals(
                    assertion.getInResponseTo()))
            {
                FSUtils.debug.error("FSAssertionArtifactHandler."
                    + "validateAssertion:"
                    + " assertion does not correspond to any valid request");
                return null;
            }
            
            if (FSServiceUtils.isSigningOn()){
                if (!verifyAssertionSignature(assertion)) {
                    FSUtils.debug.error("FSAssertionArtifactHandler."
                        + "validateAssertion:"
                        + " assertion signature verification failed");
                    return null;
                }
            }
            
            if (FSUtils.debug.messageEnabled()) {
                FSUtils.debug.message("FSAssertionArtifactHandler."
                    + "validateAssertion: Assertion signature verified");
            }
            aIDString = assertion.getAssertionID();
            // make sure it's not being used            
            if (idTimeMap.containsKey(aIDString)) {
                FSUtils.debug.error(
                    "FSAssertionArtifactHandler.validateAssertion: Assertion: "
                    + aIDString + " is used");
                return null;
            }
            // check issuer of the assertions
            issuer = assertion.getIssuer();
            try {
                if (idpEntityId != null) {
                    if (!idpEntityId.equals(issuer)) {
                        FSUtils.debug.error("FSAssertionArtifactHandler."
                            + "validateAssertion: "
                            + "Assertion issuer is not the entity where "
                            + "AuthnRequest was sent originally.");
                        return null;
                    }
                } else {
                    FSUtils.debug.error("FSAssertionArtifactHandler."
                        + "validateAssertion: "
                        + "Assertion issuer is: " + issuer);
                    IDFFMetaManager metaManager = 
                        FSUtils.getIDFFMetaManager();
                    IDPDescriptorType idpDesc= 
                        metaManager.getIDPDescriptor(realm, issuer);
                    if (idpDesc == null){
                        FSUtils.debug.error("FSAssertionArtifactHandler."
                            + "validateAssertion:"
                            + " Assertion issuer is not on the trust list");
                        return null;
                    }
                    setProviderDescriptor(idpDesc);
                    setProviderEntityId(issuer);
                }
            } catch(Exception ex){
                FSUtils.debug.error("FSAssertionArtifactHandler."
                    + "validateAssertion: "
                    + "Assertion issuer is not on the trust list");
                return null;
            }
            
            // must be valid(timewise)
            if (!assertion.isTimeValid()) {
                FSUtils.debug.error(
                    "FSAssertionArtifactHandler.validateAssertion:"
                    + " Assertion's time is not valid.");
                return null;
            }
            
            
            // TODO: IssuerInstant of the assertion is within a few minutes
            // This is a MAY in spec. Which number to use for the few minutes?
            
            // if present, target of the assertions must == local server IP
            Conditions conds = assertion.getConditions();
            if (!forThisServer(conds)) {
                FSUtils.debug.error("FSAssertionArtifactHandler."
                    + "validateAssertion: "
                    + "assertion is not issued for this site.");
                return null;
            }
            
            //for each assertion, loop to check each statement
            boolean authnStatementFound = false;
            if (assertion.getStatement() != null){
                stmtIter = assertion.getStatement().iterator();
                while(stmtIter.hasNext()) {
                    statement =(Statement) stmtIter.next();
                    stmtType = statement.getStatementType();
                    if (stmtType == Statement.AUTHENTICATION_STATEMENT) {
                        FSAuthenticationStatement authStatement = 
                            (FSAuthenticationStatement)statement;
                        authnStatementFound = true;
                        try {
                            if (FSUtils.debug.messageEnabled()) {
                                FSUtils.debug.message(
                                    "FSAssertionArtifactHandler."
                                    + "validateAssertion: "
                                    + "validating AuthenticationStatement:"
                                    + authStatement.toXMLString());
                            }
                        } catch(FSException e){
                            FSUtils.debug.error("FSAssertionArtifactHandler."
                                + "validateAssertion: Exception. "
                                + "Invalid AuthenticationStatement: ", e);
                            return null;
                        }
                        //check ReauthenticateOnOrAfter
                        reAuthnOnOrAfterDate = 
                            authStatement.getReauthenticateOnOrAfter();
                        //process SessionIndex
                        idpSessionIndex = authStatement.getSessionIndex();
                        
                        authnContextStmt = authStatement.getAuthnContext();
                        
                        subject =(FSSubject)authStatement.getSubject();
                        if (subject == null ){
                            FSUtils.debug.error("FSAssertionArtifactHandler." 
                                + "validateAssertion: Subject is null");
                            return null;
                        } else {
                            try {
                                if (FSUtils.debug.messageEnabled()) {
                                    FSUtils.debug.message(
                                        "FSAssertionArtifactHandler."
                                        + "validateAssertion: "
                                        + "found Authentication Statement. "
                                        + "Subject = " 
                                        + subject.toXMLString());
                                }
                            } catch(FSException e){
                                FSUtils.debug.error(
                                    "FSAssertionArtifactHandler."
                                    + "validateAssertion: "
                                    + " Exception. Invalid subject: ", e);
                                continue;
                            }
                        }
                        
                        // ConfirmationMethod of each subject must be set to 
                        //bearer
                        if (((subConf = 
                            subject.getSubjectConfirmation()) == null) ||
                            ((confMethods = 
                                subConf.getConfirmationMethod())== null) ||
                            (confMethods.size() != 1)) 
                        {
                            FSUtils.debug.error("FSAssertionArtifactHandler."
                                + "validateAssertion: "
                                + "missing or extra ConfirmationMethod.");
                            return null;
                        }
                        if (((confMethod = 
                            (String)confMethods.iterator().next()) == null) ||
                            !((confMethod.equals(
                                SAMLConstants.CONFIRMATION_METHOD_BEARER)) ||
                            (confMethod.equals(
                                SAMLConstants.CONFIRMATION_METHOD_ARTIFACT)) ||
                            (confMethod.equals(SAMLConstants.
                                DEPRECATED_CONFIRMATION_METHOD_ARTIFACT))))
                        {
                            FSUtils.debug.error("FSAssertionArtifactHandler."
                                + "validateAssertion: wrong "
                                + "ConfirmationMethod");
                            return null;
                        }
                        if (FSUtils.debug.messageEnabled()) {
                            FSUtils.debug.message("FSAssertionArtifactHandler."
                                + "validateAssertion: Confirmation method: " 
                                + confMethod);      
                        }
                    } else if (stmtType == Statement.ATTRIBUTE_STATEMENT) {
                        AttributeStatement attrStatement = 
                                  (AttributeStatement)statement;
                        if (!checkForAttributeStatement(attrStatement)) {
                            attrStatements.add(attrStatement);
                        }
                        
                    }
                }
            }
            
            if (!authnStatementFound){
                if (FSUtils.debug.messageEnabled()) {
                    FSUtils.debug.message("FSAssertionArtifactHandler."
                        + "validateAssertion: "
                        + "No Authentication statement found in the Assertion. "
                        + "User is not authenticated by the IDP");
                }
                return null;
            }
            if (FSUtils.debug.messageEnabled()) {
                FSUtils.debug.message("FSAssertionArtifactHandler."
                    + "validateAssertion: Adding " 
                    + aIDString 
                    + " to idTimeMap.");
            }
            // add the assertion to idTimeMap
            if ((date = conds.getNotOnorAfter()) != null) {
                cGoThrough.addElement(aIDString);
                idTimeMap.put(aIDString, new Long(date.getTime()));
            } else {
                cPeriodic.addElement(aIDString);
                // it doesn't matter what we store for the value.
                idTimeMap.put(aIDString, aIDString);
            }            
            securityAssertions = assertion.getDiscoveryCredential();
        }
        
        if (subject == null) {
            FSUtils.debug.error("FSAssertionArtifactHandler.validateAssertion:"
                + " couldn't find Subject.");
            return null;
        }
        return subject;
    }

    /**
     * Checks the attribute statement for boot strap statement or auto fed
     * attribute  statement. 
     * @param attrStatement AttributeStatement.
     * @return true if the <code>AttributeStatement</code> is of type
     *          discovery boot strap or the auto federation statement.
     */
    private boolean checkForAttributeStatement(
       AttributeStatement attrStatement) {

        List attributes = attrStatement.getAttribute();
        if (attributes == null || attributes.size() == 0) {
            return false;
        }

        Iterator iter = attributes.iterator();
        Attribute attribute = (Attribute)iter.next();

        if (attribute.getAttributeName().equals(
            IFSConstants.DISCO_RESOURCE_OFFERING_NAME)) 
        {
            bootStrapStatement = attrStatement;
            return true;

        } else if(attribute.getAttributeName().equals(
            IFSConstants.AUTO_FED_ATTR))
        {
            _autoFedStatement = attrStatement;
            List attrValue = null;

            try {
                attrValue = attribute.getAttributeValue();
            } catch (SAMLException se) {
                FSUtils.debug.error("FSAssertionArtifactHandler.checkFor" +
                    "AttributeStatement: ", se);
            }

            String _autoFedValue = null;
            if (attrValue != null && attrValue.size() != 0) {
                Iterator iter2 = attrValue.iterator();
                Element elem = (Element)iter2.next();
                _autoFedValue = XMLUtils.getElementValue(elem);
            }

            String enabledStr = IDFFMetaUtils.getFirstAttributeValueFromConfig(
                hostConfig, IFSConstants.ENABLE_AUTO_FEDERATION);
            
            if (enabledStr != null && enabledStr.equalsIgnoreCase("true") &&
                _autoFedValue != null) 
            {
                autoFedSearchMap = new HashMap(); 
                Set set = new HashSet();
                set.add(_autoFedValue);
                autoFedSearchMap.put(
                    IDFFMetaUtils.getFirstAttributeValueFromConfig(
                        hostConfig, IFSConstants.AUTO_FEDERATION_ATTRIBUTE),
                    set);
            }

            return true;
        }
        return false;
    }
    
    protected boolean verifyAssertionSignature(FSAssertion assertion) {
        FSUtils.debug.message(
            "FSAssertionArtifactHandler.verifyAssertionSignature: Called");
        try {
            if (!assertion.isSigned()){
                if (FSUtils.debug.messageEnabled()) {
                    FSUtils.debug.message("FSAssertionArtifactHandler."
                        + "verifyAssertionSignature: Assertion is not signed");
                }
                return false;
            }

            X509Certificate cert = KeyUtil.getVerificationCert(
                idpDescriptor, idpEntityId, true);
            
            if (cert == null) {
                if (FSUtils.debug.messageEnabled()) {
                    FSUtils.debug.message("FSAssertionArtifactHandler."
                        + "verifyAssertionSignature: couldn't obtain "
                        + "this site's cert.");
                }
                throw new SAMLResponderException(
                    FSUtils.bundle.getString(IFSConstants.NO_CERT));
            }
            XMLSignatureManager manager = XMLSignatureManager.getInstance();
            if (authnResponse != null) {
                if (FSUtils.debug.messageEnabled()) {
                    FSUtils.debug.message("FSAssertionArtifactHander." +
                    "verifyAssertionSignature:  xml string to be verified:" +
                    XMLUtils.print((Node)
                        authnResponse.getDOMElement().getOwnerDocument())); 
                }
                return manager.verifyXMLSignature(
                    authnResponse.getDOMElement().getOwnerDocument(),cert);
            } else if(samlResponseElt != null) {
                if (FSUtils.debug.messageEnabled()) {
                    FSUtils.debug.message("FSAssertionArtifactHander." +
                    "verifyAssertionSignature:  xml string to be verified:" +
                    XMLUtils.print((Node) samlResponseElt.getOwnerDocument())); 
                }
                return manager.verifyXMLSignature(
                    samlResponseElt.getOwnerDocument(), cert);
            } else {
                return false;
            }

        } catch(Exception e){
            FSUtils.debug.error("FSAssertionArtifactHandler."
                + "verifyAssertionSignature: "
                + "Exception occured while verifying IDP's signature:", e);
            return false;
        }
    }
    
    protected boolean forThisServer(Conditions conds) {
        FSUtils.debug.message(
            "FSAssertionArtifactHandler.forThisServer: Called");
        if ((conds == null) ||
            (hostEntityId == null) ||
            (hostEntityId.length() == 0)) 
        {
            return true;
        }        
        Set targetConds = conds.getAudienceRestrictionCondition();
        if ((targetConds == null) ||(targetConds.isEmpty())) {
            return true;
        }        
        boolean forThis = false;
        Iterator tcIter = targetConds.iterator();
        AudienceRestrictionCondition targetCond = null;
        while(tcIter.hasNext()) {
            targetCond =(AudienceRestrictionCondition) tcIter.next();
            if (targetCond.containsAudience(hostEntityId)) {
                forThis = true;
                if (FSUtils.debug.messageEnabled()) {
                    FSUtils.debug.message("FSAssertionArtifactHandler."
                        + "forThisServer: Assertion is validated to be"
                        + "for this server");
                }
                break;
            }
        }
        return forThis;
    }
    
    protected int generateToken(
        NameIdentifier ni,
        int handleType, 
        NameIdentifier niIdp,
        Map env
    ) 
    {
        FSUtils.debug.message(
            "FSAssertionArtifactHandler.generateToken: Called");
        if ((ni == null)){
            FSUtils.debug.error("FSAssertionArtifactHandler."
                + "generateToken: Invalid userDN input");
            return FederationSPAdapter.SSO_FAILED;
        }
        try {
            String name = ni.getName();
            String nameSpace = ni.getNameQualifier();
            if ((nameSpace == null) || (nameSpace.length() == 0)) {
                nameSpace = hostEntityId;
            }

            if (FSUtils.debug.messageEnabled()) {
                FSUtils.debug.message("FSAssertionArtifactHandler."
                    + "generateToken: Trying to get userDN for opaqueHandle= "
                    + name 
                    + " ,securityDomain= " 
                    + nameSpace 
                    + " And HandleType=" 
                    + handleType);
            }
            
            String affiliationID = authnRequest.getAffiliationID();
            FSAccountFedInfoKey fedKey = 
                new FSAccountFedInfoKey(nameSpace, name);
            FSAccountManager accountManager = FSAccountManager.getInstance(
                hostMetaAlias);
            String userID = accountManager.getUserID(fedKey, realm, env);
            FSAccountFedInfo fedInfo = null;
            if (userID == null) {
                if (niIdp != null && nameSpace.equals(affiliationID)) {
                    fedKey = new FSAccountFedInfoKey(affiliationID, 
                        niIdp.getName());
                    userID =  accountManager.getUserID(fedKey, realm, env);
                    if (userID != null) { 
                        FSAccountFedInfo oldInfo = 
                            accountManager.readAccountFedInfo(
                                userID, affiliationID);
                        if (oldInfo != null) {
                            accountManager.removeAccountFedInfo(
                                userID, oldInfo);
                        }
                        fedInfo = new FSAccountFedInfo(
                            idpEntityId, ni, niIdp, true);
                        fedInfo.setAffiliation(true);
                        fedKey = new FSAccountFedInfoKey(nameSpace, name); 
                        accountManager.writeAccountFedInfo(
                            userID, fedKey, fedInfo);
                    } else {
                        FSUtils.debug.error(
                            "FSAssertionArtifactHandler.generateToken: " +
                            "Can't dereference handle. fedKey=" +
                            fedKey.toString());
                        return FederationSPAdapter.
                            SSO_FAILED_FEDERATION_DOESNOT_EXIST;
                    }
                } else {
                    // Check if there is any 6.2 format? 
                    FSAccountFedInfoKey oldKey = new FSAccountFedInfoKey(
                        idpEntityId, name);

                    if (oldKey != null) {
                        userID = accountManager.getUserID(oldKey, realm, env);
                        if (userID != null) {
                            fedInfo = accountManager.readAccountFedInfo(
                                    userID, idpEntityId); 
                            if (fedInfo != null && fedInfo.isFedStatusActive()){
                                // rewrite it.
                                NameIdentifier localNI = 
                                    fedInfo.getLocalNameIdentifier();
                                if (localNI != null) {
                                    localNI.setNameQualifier(hostEntityId);
                                }
                                accountManager.removeAccountFedInfo(
                                    userID, fedInfo);
                                NameIdentifier remoteNI =
                                    fedInfo.getRemoteNameIdentifier();
                                if (remoteNI != null) {
                                    remoteNI.setNameQualifier(hostEntityId);
                                }
                                fedInfo = new FSAccountFedInfo(
                                    idpEntityId,
                                    localNI,
                                    remoteNI,
                                    true);
                                accountManager.removeAccountFedInfoKey(
                                    userID, oldKey);
                                FSAccountFedInfoKey newKey = 
                                    new FSAccountFedInfoKey(hostEntityId, name);
                                accountManager.writeAccountFedInfo(
                                    userID, newKey, fedInfo);
                            } else {
                                FSUtils.debug.error(
                                    "FSAssertionArtifactHandler." +
                                    "generateToken: Can't dereference handle.");
                                return FederationSPAdapter.
                                SSO_FAILED_FEDERATION_DOESNOT_EXIST;
                            }
                        } else {
                            String enabledStr =
                                IDFFMetaUtils.getFirstAttributeValueFromConfig(
                                    hostConfig, 
                                    IFSConstants.ENABLE_AUTO_FEDERATION);
                            if (enabledStr != null && 
                                enabledStr.equalsIgnoreCase("true") &&
                                _autoFedStatement != null) 
                            {
                                userID = accountManager.getUserID(
                                    autoFedSearchMap, realm, null); 
                                if (userID != null) {
                                    FSAccountFedInfoKey newKey = 
                                        new FSAccountFedInfoKey(
                                            hostEntityId, name);
                                    fedInfo = 
                                        new FSAccountFedInfo(
                                            idpEntityId,
                                            null,
                                            ni,
                                            true);
                                    accountManager.writeAccountFedInfo(
                                        userID, newKey, fedInfo);
                                } else {
                                    FSUtils.debug.error(
                                        "FSAssertionArtifactHandler. " +
                                        "generateToken:" +
                                        "Can't dereference handle.");
                                    return 
                                        FederationSPAdapter.SSO_FAILED_AUTO_FED;
                                }
                            } else {
                                FSUtils.debug.error(
                                    "FSAssertionArtifactHandler." +
                                    "generateToken: Can't dereference handle.");
                                return FederationSPAdapter.
                                    SSO_FAILED_FEDERATION_DOESNOT_EXIST;
                            }
                        }
                    } else {
                        FSUtils.debug.error("FSAssertionArtifactHandler." +
                            "generateToken: Can't dereference handle.");
                        return FederationSPAdapter.
                            SSO_FAILED_FEDERATION_DOESNOT_EXIST;
                    }
                }
            } else {
                if (affiliationID != null) {
                    fedInfo = accountManager.readAccountFedInfo(
                        userID, affiliationID);
                } else {
                    fedInfo = accountManager.readAccountFedInfo(
                        userID, idpEntityId, name);
                }
                if (fedInfo == null){
                    FSUtils.debug.error(
                        "FSAssertionArtifactHandler.generateToken: "
                        + "User's account is not federated, id=" + userID);
                    return 
                        FederationSPAdapter.SSO_FAILED_FEDERATION_DOESNOT_EXIST;
                }
            }
            //get AuthnLevel from authnContext
            String authnContextClassRef = null;
            int authnLevel = 0;
            Map authnContextInfoMap = 
                FSServiceUtils.getSPAuthContextInfo(hostConfig);
            if (authnContextStmt != null && 
                authnContextStmt.getAuthnContextClassRef() != null && 
                authnContextStmt.getAuthnContextClassRef().length() != 0)
            {
                   
                authnContextClassRef = 
                    authnContextStmt.getAuthnContextClassRef();
                if (authnContextClassRef != null && 
                    authnContextClassRef.length() != 0)
                {
                    if (FSUtils.debug.messageEnabled()) {
                        FSUtils.debug.message("FSAssertionArtifactHandler."
                            + "generateToken: AuthnContextClassRef "
                            + "found in AuthenticationStatement:" 
                            + authnContextClassRef);                    
                    }
                    FSSPAuthenticationContextInfo authnContextInfo = 
                        (FSSPAuthenticationContextInfo)authnContextInfoMap
                            .get(authnContextClassRef);
                    if (authnContextInfo != null){
                        authnLevel = authnContextInfo.getAuthenticationLevel();
                    } else {
                        FSUtils.debug.error("FSAssertionArtifactHandler."
                            + "generateToken: Could not find "
                            + "AuthnContextClassInfo for authnContextClassRef: " 
                            + authnContextClassRef 
                            + "Using default authnContextClass");
                        authnContextClassRef = null;
                    }
                }
            } else {
                FSUtils.debug.warning(
                    "FSAssertionArtifactHandler.generateToken: " +
                    "Could not find AuthnContextClassRef in the " +
                    "AuthenticationStatement. Using default authnContextClass");
            }
            if (authnContextClassRef == null || 
                authnContextClassRef.length() == 0)
            {
                authnContextClassRef = 
                    IDFFMetaUtils.getFirstAttributeValueFromConfig(
                        hostConfig, IFSConstants.DEFAULT_AUTHNCONTEXT);
                FSSPAuthenticationContextInfo authnContextInfo = 
                    (FSSPAuthenticationContextInfo)authnContextInfoMap
                        .get(authnContextClassRef);
                if (authnContextInfo != null){
                    authnLevel = authnContextInfo.getAuthenticationLevel();
                } else {
                    FSUtils.debug.error("FSAssertionArtifactHandler."
                        + "generateToken: Could not find authentication level "
                        + "for default authentication context class");
                    return FederationSPAdapter.SSO_FAILED;
                }
            }
            
            Map valueMap = new HashMap();
            valueMap.put(SessionProvider.PRINCIPAL_NAME, userID);
            valueMap.put(SessionProvider.REALM, realm);
            valueMap.put(
                SessionProvider.AUTH_LEVEL, String.valueOf(authnLevel));
            valueMap.put(SessionProvider.AUTH_INSTANT, getAuthInstant());
            valueMap.put("idpEntityID", idpEntityId);
            //valueMap.put("resourceOffering",            
            //valueMap.put("securityToken",
            
            SessionProvider sessionProvider = SessionManager.getProvider();
            Object ssoSession;
            try {
                ssoSession = sessionProvider.createSession(
                    valueMap, request, response, 
                    new StringBuffer(this.relayState));
            } catch (SessionException se) {
                FSUtils.debug.error("FSAssertionArtifactHandler.generateToken:"
                    + "cannot generate token:", se);
                int failureCode = se.getErrCode();
                if (failureCode == SessionException.AUTH_USER_INACTIVE) {
                    failureCode = 
                        FederationSPAdapter.SSO_FAILED_AUTH_USER_INACTIVE;
                } else if (failureCode == SessionException.AUTH_USER_LOCKED) {
                    failureCode =
                        FederationSPAdapter.SSO_FAILED_AUTH_USER_LOCKED;
                } else if (failureCode == SessionException.AUTH_ACCOUNT_EXPIRED)
                {
                    failureCode = 
                        FederationSPAdapter.SSO_FAILED_AUTH_ACCOUNT_EXPIRED;
                } else {
                    failureCode = FederationSPAdapter.
                        SSO_FAILED_TOKEN_GENERATION;
                }
                   
                return failureCode;
            }
            try {
                sessionProvider.addListener(
                    ssoSession, new FSTokenListener(hostMetaAlias));
            } catch (Exception e) {
                if (FSUtils.debug.messageEnabled()) {
                    FSUtils.debug.message(
                        "FSAssertionArtifactHandler.generateToken:" +
                        "Couldn't add listener to session:", e);
                }
            }
            String value = sessionProvider.getSessionID(ssoSession);
            
            ssoToken = ssoSession;
            Iterator iter = null;
            //Set fed cookie
            String fedCookieName = SystemConfigurationUtil.getProperty(IFSConstants.FEDERATE_COOKIE_NAME);
            String fedCookieValue = "yes";
            for (String domain : SystemConfigurationUtil.getCookieDomainsForRequest(request)) {
                CookieUtils.addCookieToResponse(response, CookieUtils.newCookie(fedCookieName, fedCookieValue,
                        IFSConstants.PERSISTENT_COOKIE_AGE, "/", domain));
            }

            //keep local session ref
            FSSessionManager sessionManager = 
                        FSSessionManager.getInstance(hostMetaAlias);
            FSSession session = sessionManager.getSession(userID, value);
            if (session != null){
                if (FSUtils.debug.messageEnabled()) {
                    FSUtils.debug.message("FSAssertionArtifactHandler."
                        + "generateToken: An Existing session found for userID:"
                        + userID + " And SessionID: " + value 
                        + " Adding partner to the Session");
                }
                session.addSessionPartner(new FSSessionPartner(
                    idpEntityId, true));
                session.setSessionIndex(idpSessionIndex);
                sessionManager.addSession(userID,session);
            } else {
                if (FSUtils.debug.messageEnabled()) {
                    FSUtils.debug.message("FSAssertionArtifactHandler."
                        + "generateToken: No existing session found for userID:"
                        + userID + " And SessionID: " + value 
                        + " Creating a new Session");
                    }
                    session = new FSSession(value);
                    session.addSessionPartner(new FSSessionPartner(
                        idpEntityId, true));
                    if (idpSessionIndex != null){
                        session.setSessionIndex(idpSessionIndex);
                    }
                    sessionManager.addSession(userID, session);
            }

            // keep authncontext in FSSession.
            if (authnContextClassRef != null) {
                session.setAuthnContext(authnContextClassRef);
            }

            if (fedInfo != null) {
                session.setAccountFedInfo(fedInfo);
            }

            // keep the attr statement in FSSession.
            if (bootStrapStatement != null) {
                session.setBootStrapAttributeStatement(bootStrapStatement);
            }

            if (_autoFedStatement != null) {
                session.setAutoFedStatement(_autoFedStatement);
            }

            if (attrStatements.size() != 0) {
                session.setAttributeStatements(attrStatements);
                Map attributeMap = null;
                setAttributeMapper();
                if (realmAttributeMapper != null) { 
                    attributeMap = realmAttributeMapper.getAttributes(
                        attrStatements, realm, hostEntityId, 
                        idpEntityId, ssoToken);
                } else if (attributeMapper != null) {
                    attributeMap = attributeMapper.getAttributes(
                        attrStatements, hostEntityId, 
                        idpEntityId, ssoToken);
                }
                if (FSUtils.debug.messageEnabled()) {
                    FSUtils.debug.message("FSAssertionArtifactHandler." +
                        "generateToken: Attribute map :" + attributeMap);
                } 
                if (attributeMap != null) {
                    setAttributeMap(ssoToken, attributeMap);  
                }
            }

            if (securityAssertions != null) {
                session.setBootStrapCredential(securityAssertions);
            }

            return FederationSPAdapter.SUCCESS;
        } catch(Exception e) {
            FSUtils.debug.error("FSAssertionArtifactHandler.generateToken: "
                + "Exception Occured ", e );
            return FederationSPAdapter.SSO_FAILED;
        }
    }
    
    
    protected void processSAMLRequest() {
    }
    
    
    protected int doSingleSignOn(
        NameIdentifier ni, 
        int handleType, 
        NameIdentifier niIdp,
        Map env
    ) 
    {
        FSUtils.debug.message(
            "FSAssertionArtifactHandler.doSingleSignOn: Called");
        int returnCode = generateToken(ni, handleType, niIdp, env);
        if (returnCode != FederationSPAdapter.SUCCESS) {
            String[] data = 
                { FSUtils.bundle.getString("failGenerateSSOToken") };
            LogUtil.error(Level.INFO,LogUtil.FAILED_SSO_TOKEN_GENERATION, data,
                ssoToken);
        }
            
        return returnCode;
    }
    
    protected void redirectToResource(String resourceURL) throws FSException {
    }
    
    
    protected int doAccountFederation(NameIdentifier ni) {
        FSUtils.debug.message(
            "FSAssertionArtifactHandler.doAccountFederation:Called");
        if (ni == null){
            FSUtils.debug.error(
                "FSAssertionArtifactHandler.doAccountFederation:" +
                FSUtils.bundle.getString("invalidInput"));
            return FederationSPAdapter.FEDERATION_FAILED;
        }
        Object ssoToken = null;
        SessionProvider sessionProvider = null;
        try {
            sessionProvider = SessionManager.getProvider();
        } catch (SessionException se) {
            FSUtils.debug.error(
                "FSAssertionArtifactHandler.doAccountFederation: " +
                "Couldn't obtain session provider:", se);
            String[] data = 
                { FSUtils.bundle.getString("failGenerateSSOToken") };
            LogUtil.error(Level.INFO,LogUtil.FAILED_SSO_TOKEN_GENERATION, data);
            return FederationSPAdapter.
                FEDERATION_FAILED_SSO_TOKEN_GENERATION;
        }
        try {
            ssoToken = sessionProvider.getSession(request);
            if ((ssoToken == null) ||(!sessionProvider.isValid(ssoToken))) {
                if (FSUtils.debug.messageEnabled()) {
                    FSUtils.debug.message("FSAssertionArtifactHandler."
                    + "doAccountFederation: couldn't obtain session from "
                    + "cookie");
                }
                ssoToken = null;
            }
        } catch(SessionException se) {
            if (FSUtils.debug.messageEnabled()) {
                FSUtils.debug.message("FSAssertionArtifactHandler."
                    + "doAccountFederation: exception when getting session "
                    + "from cookie:");
            }
            ssoToken = null;
        }

        // try URL rewriting
        FSSessionManager sessionManager = null;
        /*
        String cookieRewriteEnabled = SystemConfigurationUtil.getProperty(
               "com.sun.identity.cookieRewritingInPath", "false");
        if (Boolean.valueOf(cookieRewriteEnabled).booleanValue()
            && ssoToken == null) 
        if (Boolean.valueOf(cookieRewriteEnabled).booleanValue() 
           && (ssoToken == null)) {
            try {
                sessionManager = FSSessionManager.getInstance(hostMetaAlias);
                ssoToken = sessionManager.getLocalSessionToken(
                                        authnRequest.getRequestID());
                if ((ssoToken == null) ||(!sessionProvider.isValid(ssoToken))) {
                    FSUtils.debug.error("FSAssertionArtifactHandler."
                        + "doAccountFederation: "
                        + FSUtils.bundle.getString("failGenerateSSOToken"));
                    String[] data = 
                        { FSUtils.bundle.getString("failGenerateSSOToken") };
                    LogUtil.error(
                        Level.INFO,LogUtil.FAILED_SSO_TOKEN_GENERATION, data);
                    return FederationSPAdapter.
                        FEDERATION_FAILED_SSO_TOKEN_GENERATION;
                }
                this.relayState = sessionProvider.rewriteURL(
                    ssoToken, this.relayState);
                request.setAttribute(
                    SystemConfigurationUtil.getProperty(
                        "com.iplanet.am.cookie.name"),
                    sessionProvider.getSessionID(ssoToken));
            } catch (Exception ex) {
                FSUtils.debug.error("FSAssertionArtifactHandler."
                    + "doAccountFederation: " 
                    + FSUtils.bundle.getString("failGenerateSSOToken"), ex);
                String[] data = 
                    { FSUtils.bundle.getString("failGenerateSSOToken") };
                LogUtil.error(
                    Level.INFO,LogUtil.FAILED_SSO_TOKEN_GENERATION, data);
                return FederationSPAdapter.
                    FEDERATION_FAILED_SSO_TOKEN_GENERATION;
            }
        }
        */

        if (ssoToken == null && nameIDPolicy != null && 
                nameIDPolicy.equals(IFSConstants.NAME_ID_POLICY_ONETIME)) 
        {
            try {
                ssoToken = generateAnonymousToken(response);
            } catch (SessionException se) {
                int failureCode = se.getErrCode();
                if (failureCode == SessionException.AUTH_USER_INACTIVE) {
                    failureCode = FederationSPAdapter.
                        FEDERATION_FAILED_ANON_AUTH_USER_INACTIVE;
                } else if (failureCode == SessionException.AUTH_USER_LOCKED) {
                    failureCode = FederationSPAdapter.
                        FEDERATION_FAILED_ANON_AUTH_USER_LOCKED;
                } else if (failureCode == SessionException.AUTH_ACCOUNT_EXPIRED)
                {
                    failureCode = FederationSPAdapter.
                        FEDERATION_FAILED_ANON_AUTH_ACCOUNT_EXPIRED;
                } else {
                    failureCode = FederationSPAdapter.
                        FEDERATION_FAILED_ANON_TOKEN_GENERATION;
                }
                   
                return failureCode;
            }
        }

        if (ssoToken == null) {
            FSUtils.debug.error(
                "FSAssertionArtifactHandler.doAccountFederation:"
                + "Account federation failed. Invalid session");
            return FederationSPAdapter.FEDERATION_FAILED_ANON_TOKEN_GENERATION;
        }

        try {
            String opaqueHandle = ni.getName();
            String userID = sessionProvider.getPrincipalName(ssoToken);
            String securityDomain = ni.getNameQualifier(); 
            if ((securityDomain == null) || (securityDomain.length() == 0)){
               securityDomain = hostEntityId;
            }
            FSAccountFedInfo accountInfo = new FSAccountFedInfo(
                idpEntityId, null, ni, true);
            FSAccountManager accountManager = FSAccountManager.getInstance(
                hostMetaAlias);
            FSAccountFedInfoKey fedKey = null;
            String affiliationID = authnRequest.getAffiliationID();
            if (affiliationID != null) {
                fedKey = new FSAccountFedInfoKey(affiliationID, opaqueHandle);
                accountInfo.setAffiliation(true);
            } else {
                fedKey = new FSAccountFedInfoKey(securityDomain, opaqueHandle);
            }

            if (nameIDPolicy == null ||
                !nameIDPolicy.equals(IFSConstants.NAME_ID_POLICY_ONETIME)) 
            {
                accountManager.writeAccountFedInfo(userID, fedKey, accountInfo);
            }
            //keep local session ref
            if (sessionManager == null) {
                sessionManager = FSSessionManager.getInstance(hostMetaAlias);
            }
            String sessionID = sessionProvider.getSessionID(ssoToken);
            FSSession session = sessionManager.getSession(
                userID, sessionID);
            if (session != null){
                if (FSUtils.debug.messageEnabled()) {
                    FSUtils.debug.message("FSAssertionArtifactHandler."
                        + "doAccountFederation: No existing session found "
                        + " for userID:"
                        + userID + " And SessionID: " + sessionID 
                        + " Creating a new Session");
                }
                session.addSessionPartner(
                    new FSSessionPartner(idpEntityId, true));
                session.setSessionIndex(idpSessionIndex);
            } else {
                if (FSUtils.debug.messageEnabled()) {
                    FSUtils.debug.message("FSAssertionArtifactHandler."
                        + "doAccountFederation: An Existing session found"
                        + "for userID:"
                        + userID + " And SessionID: " + sessionID 
                        + " Adding partner to the Session");
                }
                session = new FSSession(sessionID);
                session.addSessionPartner(
                    new FSSessionPartner(idpEntityId, true));
                if (idpSessionIndex != null){
                    session.setSessionIndex(idpSessionIndex);
                }
            }
            if (nameIDPolicy != null &&
                nameIDPolicy.equals(IFSConstants.NAME_ID_POLICY_ONETIME)) 
            {
                session.setOneTime(true);
                session.setUserID(userID);
            }

            String authnContextClassRef = null;
            if (authnContextStmt != null) {
                authnContextClassRef = 
                    authnContextStmt.getAuthnContextClassRef();
            }
            if ((authnContextClassRef == null) ||
                (authnContextClassRef.length() == 0))
            {
                authnContextClassRef = 
                    IDFFMetaUtils.getFirstAttributeValueFromConfig(
                        hostConfig, IFSConstants.DEFAULT_AUTHNCONTEXT);
            }
            if (authnContextClassRef != null) {
                session.setAuthnContext(authnContextClassRef);
            }
            session.setAccountFedInfo(accountInfo);
            if (bootStrapStatement != null) {
                session.setBootStrapAttributeStatement(bootStrapStatement);
            }
            
            if (attrStatements.size() != 0) {
                Map attributeMap = null;
                setAttributeMapper();
                if (realmAttributeMapper != null) {
                    attributeMap = realmAttributeMapper.getAttributes(
                        attrStatements, realm, hostEntityId,
                        idpEntityId, ssoToken);
                } else if (attributeMapper != null) {
                    attributeMap = attributeMapper.getAttributes(
                        attrStatements, hostEntityId,
                        idpEntityId, ssoToken);
                }
                if (FSUtils.debug.messageEnabled()) {
                    FSUtils.debug.message("FSAssertionArtifactHandler." +
                        "generateToken: Attribute map :" + attributeMap);
                }
                if (attributeMap != null) {
                    setAttributeMap(ssoToken, attributeMap);
                }
            }
            
            if (securityAssertions != null) {
                session.setBootStrapCredential(securityAssertions);
            }
            
            sessionManager.addSession(userID, session);

        } catch(Exception ex){
            FSUtils.debug.error(
                "FSAssertionArtifactHandler.doAccountFederation:"
                + FSUtils.bundle.getString("ExceptionOccured") , ex);
            return FederationSPAdapter.FEDERATION_FAILED_WRITING_ACCOUNT_INFO;
        }
        String[] data = {this.relayState} ;
        LogUtil.access(Level.INFO,LogUtil.ACCESS_GRANTED_REDIRECT_TO,data,
            ssoToken); 
        //Set fed cookie
        if (nameIDPolicy == null ||
            !nameIDPolicy.equals(IFSConstants.NAME_ID_POLICY_ONETIME)) 
        {
            String fedCookieName = SystemConfigurationUtil.getProperty(IFSConstants.FEDERATE_COOKIE_NAME);
            String fedCookieValue = "yes";
            for (String domain : SystemConfigurationUtil.getCookieDomainsForRequest(request)) {
                CookieUtils.addCookieToResponse(response, CookieUtils.newCookie(fedCookieName, fedCookieValue,
                        IFSConstants.PERSISTENT_COOKIE_AGE, "/", domain));
            }
        }
        
        //Name registration        
        // comment it out for now as the spec doesn't mendate this.
        /*
        try {
            // get if need name registration from sp extended meta
            String indicator = IDFFMetaUtils.getFirstAttributeValueFromConfig(
                hostConfig, IFSConstants.ENABLE_REGISTRATION_AFTER_SSO);
            if (indicator != null && indicator.equalsIgnoreCase("true")) {
                FSServiceManager serviceManager = 
                    FSServiceManager.getInstance();
                FSNameRegistrationHandler handlerObj = 
                    serviceManager.getNameRegistrationHandler(
                        realm,
                        idpEntityId,
                        IFSConstants.IDP);
                if (handlerObj != null) {
                    handlerObj.setHostedDescriptor(hostDesc);
                    handlerObj.setHostedDescriptorConfig(hostConfig);
                    handlerObj.setHostedEntityId(hostEntityId);
                    handlerObj.setMetaAlias(hostMetaAlias);
                    handlerObj.setAccountInfo(accountInfo);
                    handlerObj.handleRegistrationAfterFederation(
                        this.relayState, response);
                }
                if (!FSServieUtils.isRegisProfileSOAP(
                    sessionProvider.getPrincipalName(ssoToken),
                    idpEntityId,
                    idpDescriptor,
                    hostMetaAlias,
                    hostDesc)) 
                {
                    return FederationSPAdapter.SUCCESS;
                }
            }
        } catch (SessionException se) {
            if (FSUtils.debug.messageEnabled()) {
                FSUtils.debug.message("doAccountFederation: exception:", se);
            }
        }
        */
        // Call SP adapter
        FederationSPAdapter spAdapter = FSServiceUtils.getSPAdapter(
            hostEntityId, hostConfig);
        if (spAdapter != null) {
            FSUtils.debug.message("Invoke spAdapter");
            try {
                if (spAdapter.postSSOFederationSuccess(
                    hostEntityId, request, response, ssoToken, 
                    authnRequest, authnResponse, (FSResponse)samlResponse))
                {
                    // return true if service provider SPI redirection happened
                    return FederationSPAdapter.SUCCESS;
                }
            } catch (Exception e) {
                // log run time exception in Adapter
                // implementation, continue
                FSUtils.debug.error("FSAssertionArtifactHandler"
                    + " SPAdapter.postSSOFederationSuccess", e);
            }
        }

        try {
            redirectToResource(this.relayState);
            return FederationSPAdapter.SUCCESS;
        } catch(Exception e){
            return FederationSPAdapter.FEDERATION_FAILED;
        }
    }

    /**
     * Generates an anonymous token for onetime case.
     */
    protected Object generateAnonymousToken(HttpServletResponse response)
        throws SessionException 
    {

        FSUtils.debug.message("FSAssertionArtifactHandler.generateAnonymous");
 
        try {
            Map valueMap = new HashMap();
            valueMap.put(SessionProvider.PRINCIPAL_NAME, ANONYMOUS_PRINCIPAL);
            valueMap.put(SessionProvider.REALM, realm);
            // default auth level to "0" for anonymous 
            valueMap.put(SessionProvider.AUTH_LEVEL, "0");
            valueMap.put(SessionProvider.AUTH_INSTANT, getAuthInstant());
            valueMap.put("idpEntityID", idpEntityId);

            SessionProvider sessionProvider = SessionManager.getProvider();
            Object ssoSession = sessionProvider.createSession(
                    valueMap, request, response, 
                    new StringBuffer(this.relayState));
            try {
                sessionProvider.addListener(
                    ssoSession, new FSTokenListener(hostMetaAlias));
            } catch (Exception e) {
                FSUtils.debug.error(
                    "FSAssertionArtifactHandler.generateAnonymousToken:" +
                    "Couldn't add listener to session:", e);
            }

            return ssoSession;
        } catch (SessionException se) {
            FSUtils.debug.error(
                "FSAssertionArtifactHandler.genAnonymousToken failed.", se);
            throw se;
        } catch (Exception ae) {
            FSUtils.debug.error(
               "FSAssertionArtifactHandler.generateAnonymousToken failed.", ae);
            return null;
        }

    }
    
    protected FSAuthnRequest getInResponseToRequest(String requestID) {
        FSUtils.debug.message(
            "FSBrowserArtifactConsumerHandler.getInResponseToRequest: Called");
        FSSessionManager sessionManager = 
            FSSessionManager.getInstance(hostMetaAlias);
        return authnRequest = sessionManager.getAuthnRequest(requestID);
    }
    
    protected String getProvider(String requestID) {
        FSUtils.debug.message(
            "FSAssertionArtifactHandler.getProvider: Called");
        FSSessionManager sessionManager = 
            FSSessionManager.getInstance(hostMetaAlias);
        return sessionManager.getIDPEntityID(requestID);
    }
    
    /**
     * Sets <code>IDP</code> provider descriptor.
     * @param idpDescriptor identity provider descriptor.
     */
    public void setProviderDescriptor(IDPDescriptorType idpDescriptor) {
        this.idpDescriptor = idpDescriptor;
    }

    /**
     * Sets <code>IDP</code> provider entity ID.
     * @param idpEntityId identity provider entity id.
     */
    public void setProviderEntityId(String idpEntityId) {
        this.idpEntityId = idpEntityId;
    }

    /**
     * Gets <code>AuthInstant</code>.
     * @return <code>AuthInstant</code> in UTC date format.
     */
    public String getAuthInstant() {
        return DateUtils.toUTCDateFormat(newDate());
    }
    
    /**
     * Checks if the proxying is enabled. It will be checking if the proxy
     * service provider descriptor is set in the session manager for the
     * specific request ID.
     * @param requestID authentication request id which is created by the
     *                  proxying IDP to the authenticating IDP.
     * @return true if the proxying is enabled.
     */
    protected boolean isIDPProxyEnabled(String requestID) {
        FSSessionManager sessionManager = 
            FSSessionManager.getInstance(hostMetaAlias);
        return (sessionManager.getProxySPDescriptor(requestID) != null);
    }

    /**
     * Sends the proxy authentication response to the proxying service
     * provider which has originally requested for the authentication.
     * @param requestID authnRequest id that is sent to the authenticating
     *  Identity Provider.
     */
    protected void sendProxyResponse(String requestID) {
        FSUtils.debug.message("FSAssertionArtifactHandler.sendProxyResponse::");
        FSSessionManager sessionManager =
            FSSessionManager.getInstance(hostMetaAlias);
        FSAuthnRequest origRequest = 
            sessionManager.getProxySPAuthnRequest(requestID);
        if (FSUtils.debug.messageEnabled()) {
            try {
                FSUtils.debug.message("FSAssertionHandler.sendProxyResponse:" +
                    origRequest.toXMLString());
            } catch (Exception ex) {
                FSUtils.debug.error("FSAssertionHandler.sendProxyResponse:" +
                    "toString(): Failed.", ex);
            }
        }
        SPDescriptorType proxyDescriptor = 
            sessionManager.getProxySPDescriptor(requestID);
        String proxySPEntityId = origRequest.getProviderId();
        if (FSUtils.debug.messageEnabled()) {
            FSUtils.debug.message("FSAssertionArtifactHandler.sendProxyResponse"
                + ":Original requesting service provider id:"
                + proxySPEntityId);
        }
 
        FSSession session = sessionManager.getSession(ssoToken);
        if (authnContextStmt != null) {
            String authnContext = authnContextStmt.getAuthnContextClassRef();
            session.setAuthnContext(authnContext);
        }

        session.addSessionPartner(new FSSessionPartner(
            proxySPEntityId, false));

        if (FSUtils.debug.messageEnabled()) {
            Iterator partners = session.getSessionPartners().iterator();
            while (partners.hasNext()) {
               FSSessionPartner part = (FSSessionPartner)partners.next();
               if (FSUtils.debug.messageEnabled()) {
                   FSUtils.debug.message("PARTNERS" + part.getPartner()); 
               }
            }
        }

        IDFFMetaManager metaManager = FSUtils.getIDFFMetaManager();
        BaseConfigType proxySPConfig = null;
        try {
            proxySPConfig = metaManager.getSPDescriptorConfig(
                realm, proxySPEntityId);
        } catch (Exception e) {
            FSUtils.debug.error("FSAssertionArtifactHandler.sendProxyResponse:"
                + "Couldn't obtain proxy sp meta:", e);
        }
        FSProxyHandler handler = new FSProxyHandler(
            request, response, origRequest, proxyDescriptor, 
            proxySPConfig,
            proxySPEntityId,
            origRequest.getRelayState(), ssoToken);
        IDPDescriptorType localIDPDesc = null;
        BaseConfigType localIDPConfig = null;
        String localIDPMetaAlias = null;
        try {
            localIDPDesc = metaManager.getIDPDescriptor(realm, hostEntityId);
            localIDPConfig = metaManager.getIDPDescriptorConfig(
                realm, hostEntityId);
            localIDPMetaAlias = localIDPConfig.getMetaAlias();
        } catch (Exception e) {
            FSUtils.debug.error("FSAssertionartifactHandler.sendProxyResponse:"
                + "Exception when obtaining local idp meta:", e);
        }
        
        handler.setRealm(realm);
        handler.setHostedEntityId(hostEntityId);
        handler.setHostedDescriptor(localIDPDesc);
        handler.setHostedDescriptorConfig(localIDPConfig);
        handler.setMetaAlias(localIDPMetaAlias);
        handler.processAuthnRequest(origRequest, true);
    }

    /**
     * Sets the attribute map to the Single sign on token.
     */
    private void setAttributeMap(Object token, Map attributeMap) {

        if (attributeMap == null || attributeMap.isEmpty()) {
            if (FSUtils.debug.messageEnabled()) {
                FSUtils.debug.message("FSAssertionArtifactHandler.setAttribute"+
                    "Map: Attribute map is empty");
            }
            return;
        }

        if (FSUtils.debug.messageEnabled()) {
            FSUtils.debug.message("FSAssertionArtifactHandler.setAttributeMap:"+
                " Attribute map that will be populated to ssotoken:" +
                attributeMap);
        }

        try {
            Set entrySet = attributeMap.entrySet();
            SessionProvider sessionProvider = SessionManager.getProvider();
            for (Iterator iter = entrySet.iterator(); iter.hasNext();) {
                Map.Entry entry = (Map.Entry)iter.next();
                String[] values = { (String)entry.getValue() };
                sessionProvider.setProperty(
                    token, (String)entry.getKey(), values);
            }
        } catch (Exception e) {
            if (FSUtils.debug.messageEnabled()) {
                FSUtils.debug.message(
                    "FSAssertionArtifactHandler.setAttributeMap:" +
                    "Cannot set attributes to session:", e);
            }
        }
    }

    private void setAttributeMapper() {

        String mapperStr = IDFFMetaUtils.getFirstAttributeValueFromConfig(
            hostConfig, IFSConstants.ATTRIBUTE_MAPPER_CLASS);
        if ((mapperStr != null) && (mapperStr.length() != 0)) {
            try {
                Object mapperClass = 
                    Thread.currentThread().getContextClassLoader().loadClass(
                        mapperStr).newInstance();
                if (mapperClass instanceof FSRealmAttributeMapper) {
                    realmAttributeMapper = (FSRealmAttributeMapper) mapperClass;
                } else if (mapperClass instanceof FSAttributeMapper) {
                    attributeMapper = (FSAttributeMapper) mapperClass;
                }
            } catch (Exception e) {
                FSUtils.debug.error(
                    "FSAssertionArtifactHandler.getAttributeMapper:", e);
            }
        }    
    }
}
