/*
 * Copyright 2004,2005 The Apache Software Foundation.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package org.apache.rahas.impl;

import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMNode;
import org.apache.axiom.soap.SOAPEnvelope;
import org.apache.axis2.context.MessageContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.rahas.*;
import org.apache.rahas.impl.util.*;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.util.XmlSchemaDateFormat;
import org.apache.xml.security.c14n.Canonicalizer;
import org.apache.xml.security.signature.XMLSignature;
import org.joda.time.DateTime;
import org.opensaml.Configuration;
import org.opensaml.common.SAMLException;
import org.opensaml.common.SAMLObjectBuilder;
import org.opensaml.saml2.core.*;
import org.opensaml.xml.XMLObjectBuilderFactory;
import org.opensaml.xml.io.*;
import org.opensaml.xml.schema.XSString;
import org.opensaml.xml.schema.impl.XSStringBuilder;
import org.opensaml.xml.signature.*;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import java.security.PrivateKey;
import java.security.cert.CertificateEncodingException;
import java.security.cert.X509Certificate;
import java.text.DateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * WS-Trust based SAML2 token issuer. This issuer will generate request security token responses with SAML2
 * assertions.
 */
public class SAML2TokenIssuer implements TokenIssuer {

    private String configParamName;

    private OMElement configElement;

    private String configFile;

    protected List<Signature> signatureList = new ArrayList<Signature>();

    private boolean isSymmetricKeyBasedHoK = false;

    private SAMLTokenIssuerConfig tokenIssuerConfiguration;

    private static Log log = LogFactory.getLog(SAML2TokenIssuer.class);

    /**
     * This is the main method which issues SAML2 assertions as security token responses. This method will
     * read issuer configuration and in message context properties (Basically request security token properties)
     * and will create a security token response with SAML2 assertion. The attributes are retrieved from a callback
     * class.
     * @param data A populated <code>RahasData</code> instance
     * @return A SOAP message with security token response (as per ws-trust spec) with a SAML2 assertion.
     * @throws TrustException If an error occurred while creating the response.
     */
    public SOAPEnvelope issue(RahasData data) throws TrustException {
        MessageContext inMsgCtx = data.getInMessageContext();

        this.tokenIssuerConfiguration = CommonUtil.getTokenIssuerConfiguration(this.configElement,
                this.configFile, inMsgCtx.getParameter(this.configParamName));

        if (tokenIssuerConfiguration == null) {

            if (log.isDebugEnabled()) {
                String parameterName;
                if (this.configElement != null) {
                    parameterName = "OMElement - " + this.configElement.toString();
                } else if (this.configFile != null) {
                    parameterName = "File - " + this.configFile;
                } else if (this.configParamName != null) {
                    parameterName = "With message context parameter name - " + this.configParamName;
                } else {
                    parameterName = "No method to build configurations";
                }

                log.debug("Unable to build token configurations, " + parameterName);
            }

            throw new TrustException("configurationIsNull");
        }

        SOAPEnvelope env = TrustUtil.createSOAPEnvelope(inMsgCtx
                .getEnvelope().getNamespace().getNamespaceURI());

        Crypto crypto = tokenIssuerConfiguration.getIssuerCrypto(inMsgCtx
                .getAxisService().getClassLoader());

        // Get the document
        Document doc = ((Element) env).getOwnerDocument();

        // Get the key size and create a new byte array of that size
        int keySize = data.getKeySize();
        keySize = (keySize == -1) ? tokenIssuerConfiguration.getKeySize() : keySize;

        data.setKeySize(keySize);

        // Build the assertion
        Assertion assertion = buildAssertion(doc, crypto, data);

        // Sign the assertion
        Assertion signedAssertion = signAssertion(doc, assertion, crypto);

        return createRequestSecurityTokenResponse(data, signedAssertion, env);

    }

    /**
     * This method prepares the final response. This method will create a request security token response as
     * specified in WS-Trust specification. The equivalent XML would take following format,
     * <wst:RequestSecurityTokenResponse xmlns:wst="...">
     *       <wst:TokenType>...</wst:TokenType>
     *       <wst:RequestedSecurityToken>...</wst:RequestedSecurityToken>
     *       ...
     *       <wsp:AppliesTo xmlns:wsp="...”>...</wsp:AppliesTo>
     *       <wst:RequestedAttachedReference>
     *       ...
     *       </wst:RequestedAttachedReference>
     *       <wst:RequestedUnattachedReference>
     *       ...
     *       </wst:RequestedUnattachedReference>
     *       <wst:RequestedProofToken>...</wst:RequestedProofToken>
     *       <wst:Entropy>
     *       <wst:BinarySecret>...</wst:BinarySecret>
     *       </wst:Entropy>
     *       <wst:Lifetime>...</wst:Lifetime>
     *   </wst:RequestSecurityTokenResponse>
     *
     *   Thus the RequestedSecurityToken will have SAML2 assertion passed.
     * @param rahasData The configuration data which comes with RST
     * @param assertion OpenSAM representation of SAML2 assertion.
     * @param soapEnvelope SOAP message envelope
     * @return SOAPEnvelope which includes RequestSecurityTokenResponse
     * @throws TrustException If an error occurred while creating RequestSecurityTokenResponse.
     */
    protected SOAPEnvelope createRequestSecurityTokenResponse(RahasData rahasData,
                                                      Assertion assertion,
                                                      SOAPEnvelope soapEnvelope) throws TrustException {

        OMElement requestSecurityTokenResponse;
        int wstVersion = rahasData.getVersion();
        if (RahasConstants.VERSION_05_02 == wstVersion) {
            requestSecurityTokenResponse = TrustUtil.createRequestSecurityTokenResponseElement(
                    wstVersion, soapEnvelope.getBody());
        } else {
            OMElement requestSecurityTokenResponseCollectionElement = TrustUtil
                    .createRequestSecurityTokenResponseCollectionElement(
                            wstVersion, soapEnvelope.getBody());
            requestSecurityTokenResponse = TrustUtil.createRequestSecurityTokenResponseElement(
                    wstVersion, requestSecurityTokenResponseCollectionElement);
        }

        TrustUtil.createTokenTypeElement(wstVersion, requestSecurityTokenResponse).setText(
                RahasConstants.TOK_TYPE_SAML_20);

        if (rahasData.getKeyType().endsWith(RahasConstants.KEY_TYPE_SYMM_KEY)) {
            TrustUtil.createKeySizeElement(wstVersion, requestSecurityTokenResponse, rahasData.getKeySize());
        }

        if (tokenIssuerConfiguration.isAddRequestedAttachedRef()) {
            TrustUtil.createRequestedAttachedRef(wstVersion, requestSecurityTokenResponse, "#"
                    + assertion.getID(), RahasConstants.TOK_TYPE_SAML_20);
        }

        if (tokenIssuerConfiguration.isAddRequestedUnattachedRef()) {
            TrustUtil.createRequestedUnattachedRef(wstVersion, requestSecurityTokenResponse,
                    assertion.getID(), RahasConstants.TOK_TYPE_SAML_20);
        }

        if (rahasData.getAppliesToAddress() != null) {
            TrustUtil.createAppliesToElement(requestSecurityTokenResponse, rahasData
                    .getAppliesToAddress(), rahasData.getAddressingNs());
        }

        // Use GMT time in milliseconds
        DateFormat xmlSchemaDateFormat = new XmlSchemaDateFormat();

        // Add the Lifetime element
        TrustUtil.createLifetimeElement(wstVersion, requestSecurityTokenResponse, xmlSchemaDateFormat
                .format(rahasData.getAssertionCreatedDate()),
                xmlSchemaDateFormat.format(rahasData.getAssertionExpiringDate()));

        // Create the RequestedSecurityToken element and add the SAML token
        // to it
        OMElement requestedSecurityTokenElement = TrustUtil
                .createRequestedSecurityTokenElement(wstVersion, requestSecurityTokenResponse);

        Element assertionElement = assertion.getDOM();

        requestedSecurityTokenElement.addChild((OMNode)assertionElement);

        // Store the token
        Token assertionToken = new Token(assertion.getID(),
                (OMElement) assertionElement, rahasData.getAssertionCreatedDate(),
                rahasData.getAssertionExpiringDate());

        // At this point we definitely have the secret
        // Otherwise it should fail with an exception earlier
        assertionToken.setSecret(rahasData.getEphmeralKey());
        TrustUtil.getTokenStore(rahasData.getInMessageContext()).add(assertionToken);

        if (rahasData.getKeyType().endsWith(RahasConstants.KEY_TYPE_SYMM_KEY)
                && tokenIssuerConfiguration.getKeyComputation()
                != SAMLTokenIssuerConfig.KeyComputation.KEY_COMP_USE_REQ_ENT) {

            Document doc = ((Element) soapEnvelope).getOwnerDocument();

            // Add the RequestedProofToken
            TokenIssuerUtil.handleRequestedProofToken(rahasData, wstVersion,
                    tokenIssuerConfiguration,
                    requestSecurityTokenResponse, assertionToken, doc);
        }

        return soapEnvelope;

    }

    /**
     * This methods builds the SAML2 assertion. The equivalent XML would look as follows,
     * <saml:Assertion
     *      xmlns:saml="urn:oasis:names:tc:SAML:2.0:assertion"
     *      xmlns:xs="http://www.w3.org/2001/XMLSchema"
     *      xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
     *      ID="b07b804c-7c29-ea16-7300-4f3d6f7928ac"
     *      Version="2.0"
     *      IssueInstant="2004-12-05T09:22:05Z">
     *      <saml:Issuer>https://idp.example.org/SAML2</saml:Issuer>
     *      <ds:Signature
     *        xmlns:ds="http://www.w3.org/2000/09/xmldsig#">...</ds:Signature>
     *      <saml:Subject>
     *        <saml:NameID
     *          Format="urn:oasis:names:tc:SAML:2.0:nameid-format:transient">
     *          3f7b3dcf-1674-4ecd-92c8-1544f346baf8
     *        </saml:NameID>
     *        <saml:SubjectConfirmation
     *          Method="urn:oasis:names:tc:SAML:2.0:cm:bearer">
     *          <saml:SubjectConfirmationData
     *            InResponseTo="aaf23196-1773-2113-474a-fe114412ab72"
     *            Recipient="https://sp.example.com/SAML2/SSO/POST"
     *            NotOnOrAfter="2004-12-05T09:27:05Z"/>
     *        </saml:SubjectConfirmation>
     *      </saml:Subject>
     *      <saml:Conditions
     *        NotBefore="2004-12-05T09:17:05Z"
     *        NotOnOrAfter="2004-12-05T09:27:05Z">
     *        <saml:AudienceRestriction>
     *          <saml:Audience>https://sp.example.com/SAML2</saml:Audience>
     *        </saml:AudienceRestriction>
     *      </saml:Conditions>
     *      <saml:AuthnStatement
     *        AuthnInstant="2004-12-05T09:22:00Z"
     *        SessionIndex="b07b804c-7c29-ea16-7300-4f3d6f7928ac">
     *        <saml:AuthnContext>
     *          <saml:AuthnContextClassRef>
     *            urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
     *         </saml:AuthnContextClassRef>
     *        </saml:AuthnContext>
     *      </saml:AuthnStatement>
     *      <saml:AttributeStatement>
     *        <saml:Attribute
     *          xmlns:x500="urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500"
     *          x500:Encoding="LDAP"
     *          NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
     *          Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.1"
     *          FriendlyName="eduPersonAffiliation">
     *          <saml:AttributeValue
     *            xsi:type="xs:string">member</saml:AttributeValue>
     *          <saml:AttributeValue
     *            xsi:type="xs:string">staff</saml:AttributeValue>
     *        </saml:Attribute>
     *      </saml:AttributeStatement>
     *    </saml:Assertion>
     *
     *    Reference - en.wikipedia.org/wiki/SAML_2.0#SAML_2.0_Assertions
     * @param doc The Document which comprises SAML 2 assertion.
     * @param crypto Crypto properties.
     * @param data The RST data and other configuration information.
     * @return OpenSAML representation of an Assertion.
     * @throws TrustException If an error occurred while creating the Assertion.
     */
    protected Assertion buildAssertion(Document doc, Crypto crypto, RahasData data) throws TrustException {
        //Build the assertion
        Assertion assertion = SAML2Utils.createAssertion();

        Issuer issuer = SAML2Utils.createIssuer(this.tokenIssuerConfiguration.getIssuerName());
        assertion.setIssuer(issuer);

        // Validity period
        DateTime creationDate = new DateTime();
        DateTime expirationDate = new DateTime(creationDate.getMillis() + tokenIssuerConfiguration.getTtl());

        data.setAssertionCreatedDate(creationDate.toDate());
        data.setAssertionExpiringDate(expirationDate.toDate());

        // Set the issued time.
        assertion.setIssueInstant(creationDate);

        // These variables are used to build the trust assertion
        Conditions conditions = SAML2Utils.createConditions(creationDate, expirationDate);
        assertion.setConditions(conditions);

        // Create the subject
        Subject subject;

        if (!data.getKeyType().endsWith(RahasConstants.KEY_TYPE_BEARER)) {
            subject = createSubjectWithHolderOfKeySubjectConfirmation(doc, crypto,
                    creationDate, expirationDate, data);
        } else {
            subject = createSubjectWithBearerSubjectConfirmation(data);
        }

        // Set the subject
        assertion.setSubject(subject);

        // If a SymmetricKey is used build an attr stmt, if a public key is build an authn stmt.
        if (isSymmetricKeyBasedHoK) {
            AttributeStatement attrStmt = createAttributeStatement(data);
            assertion.getAttributeStatements().add(attrStmt);
        } else {
            AuthnStatement authStmt = createAuthenticationStatement(data);
            assertion.getAuthnStatements().add(authStmt);
            if (data.getClaimDialect() != null && data.getClaimElem() != null) {
                assertion.getAttributeStatements().add(createAttributeStatement(data));
            }
        }

        return assertion;
    }

    /**
     * This method will create a SAML 2 subject based on Holder of Key confirmation method.
     * The relevant XML would look as follows,
     * <saml2:Subject>
     *       <saml2:NameID>
     *           ...
     *       </saml2:NameID>
     *       <saml2:SubjectConfirmation
     *               Method=”urn:oasis:names:tc:SAML:2.0:cm:holder-of-key”>
     *           <saml2:SubjectConfirmationData
     *                   xsi:type="saml2:KeyInfoConfirmationDataType">
     *               <ds:KeyInfo>
     *                   <ds:KeyValue>...</ds:KeyValue>
     *               </ds:KeyInfo>
     *           </saml2:SubjectConfirmationData>
     *       </saml2:SubjectConfirmation>
     *   </saml2:Subject>
     *
     * KeyInfo can be created based on public key or symmetric key. That is decided by looking at
     * the RahasData.getKeyType. TODO make sure this implementation is correct.
     * Theoretically we should be able to have many subject confirmation methods in a SAML2 subject.
     * TODO - Do we need to support that ?
     * @param doc The original XML document which we need to include the assertion.
     * @param crypto The relevant crypto properties
     * @param creationTime The time that assertion was created.
     * @param expirationTime The expiring time
     * @param data The configuration data relevant request.
     * @return OpenSAML representation of the SAML2 object.
     * @throws TrustException If an error occurred while creating the subject.
     */
    protected Subject createSubjectWithHolderOfKeySubjectConfirmation(Document doc, Crypto crypto,
                                                            DateTime creationTime,
                                                            DateTime expirationTime, RahasData data)
            throws TrustException {


        // Create the subject
        Subject subject = (Subject)CommonUtil.buildXMLObject(Subject.DEFAULT_ELEMENT_NAME);

        // Set the subject name identifier
        if (data.getPrincipal() != null) {
            setSubjectNamedIdentifierData(subject, data.getPrincipal().getName(), NameID.EMAIL);
        }

        // Create KeyInfo
        KeyInfo keyInfo = createKeyInfo(doc, crypto, data);

        //Build the Subject Confirmation
        SubjectConfirmation subjectConfirmation
                = (SubjectConfirmation)CommonUtil.buildXMLObject(SubjectConfirmation.DEFAULT_ELEMENT_NAME);

        //Set the subject Confirmation method
        subjectConfirmation.setMethod("urn:oasis:names:tc:SAML:2.0:cm:holder-of-key");

        //Build the subject confirmation data element
        KeyInfoConfirmationDataType scData = createKeyInfoConfirmationDataType();

        //Set the keyInfo element
        scData.getKeyInfos().add(keyInfo);

        // Set the validity period
        scData.setNotBefore(creationTime);
        scData.setNotOnOrAfter(expirationTime);

        //Set the subject confirmation data
        subjectConfirmation.setSubjectConfirmationData(scData);

        //set the subject confirmation
        subject.getSubjectConfirmations().add(subjectConfirmation);

        log.debug("SAML2.0 subject is constructed successfully.");
        return subject;
    }

    private KeyInfoConfirmationDataType createKeyInfoConfirmationDataType() {
        XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();
        @SuppressWarnings({"unchecked"}) SAMLObjectBuilder<KeyInfoConfirmationDataType> keyInfoSubjectConfirmationDataBuilder =
                (SAMLObjectBuilder<KeyInfoConfirmationDataType>) builderFactory.getBuilder
                        (KeyInfoConfirmationDataType.TYPE_NAME);

        //Build the subject confirmation data element
        return keyInfoSubjectConfirmationDataBuilder.
                buildObject(SubjectConfirmationData.DEFAULT_ELEMENT_NAME, KeyInfoConfirmationDataType.TYPE_NAME);
    }

    /**
     * This method creates a subject element with the bearer subject confirmation method.
     * <saml:Subject>
     *       <saml:NameIdentifier
     *                   NameQualifier="www.example.com"
     *                   Format=“urn:oasis:names:tc:SAML:1.1:nameid-
     *           format:X509SubjectName”>
     *           uid=joe,ou=people,ou=saml-demo,o=baltimore.com
     *       </saml:NameIdentifier>
     *       <saml:SubjectConfirmation>
     *           <saml:ConfirmationMethod>
     *               urn:oasis:names:tc:SAML:1.0:cm:bearer
     *           </saml:ConfirmationMethod>
     *       </saml:SubjectConfirmation>
     *   </saml:Subject>
     * @param data RahasData element
     * @return  SAML 2.0 Subject element with Bearer subject confirmation
     * @throws org.apache.rahas.TrustException if an error occurred while creating the subject.
     */
    protected Subject createSubjectWithBearerSubjectConfirmation(RahasData data) throws TrustException {

        // Create the subject
        Subject subject = (Subject)CommonUtil.buildXMLObject(Subject.DEFAULT_ELEMENT_NAME);

        //Create NameID and attach it to the subject
        setSubjectNamedIdentifierData(subject, data.getPrincipal().getName(), NameID.EMAIL);

        //Build the Subject Confirmation
        SubjectConfirmation subjectConfirmation
                = (SubjectConfirmation)CommonUtil.buildXMLObject(SubjectConfirmation.DEFAULT_ELEMENT_NAME);

        //Set the subject Confirmation method
        subjectConfirmation.setMethod("urn:oasis:names:tc:SAML:2.0:cm:bearer");

        subject.getSubjectConfirmations().add(subjectConfirmation);
        return subject;
    }


    /**
     * This method signs the given assertion with issuer's private key.
     * @param document The original RST document.
     * @param assertion Assertion to be signed.
     * @param crypto  The cryptographic properties.
     * @return The signed assertion.
     * @throws TrustException If an error occurred while signing the assertion.
     */
    protected Assertion signAssertion(Document document, Assertion assertion, Crypto crypto) throws TrustException {

        // Create a SignKeyHolder to hold the crypto objects that are used to sign the assertion
        SignKeyHolder signKeyHolder = createSignKeyHolder(crypto);

        // Build the signature object and set the credentials.
        Signature signature = (Signature) CommonUtil.buildXMLObject(Signature.DEFAULT_ELEMENT_NAME);

        signature.setSigningCredential(signKeyHolder);
        signature.setSignatureAlgorithm(signKeyHolder.getSignatureAlgorithm());
        signature.setCanonicalizationAlgorithm(Canonicalizer.ALGO_ID_C14N_EXCL_OMIT_COMMENTS);

        //Build the KeyInfo element and set the certificate
        try {
            KeyInfo keyInfo = (KeyInfo) CommonUtil.buildXMLObject(KeyInfo.DEFAULT_ELEMENT_NAME);
            X509Data x509Data = (X509Data) CommonUtil.buildXMLObject(X509Data.DEFAULT_ELEMENT_NAME);
            org.opensaml.xml.signature.X509Certificate cert
                    = (org.opensaml.xml.signature.X509Certificate) CommonUtil.buildXMLObject
                    (org.opensaml.xml.signature.X509Certificate.DEFAULT_ELEMENT_NAME);
            String value
                    = org.apache.xml.security.utils.Base64.encode(signKeyHolder.getEntityCertificate().getEncoded());

            cert.setValue(value);
            x509Data.getX509Certificates().add(cert);
            keyInfo.getX509Datas().add(x509Data);

            signature.setKeyInfo(keyInfo);
            assertion.setSignature(signature);

            signatureList.add(signature);

            //Marshall and Sign
            MarshallerFactory marshallerFactory = org.opensaml.xml.Configuration.getMarshallerFactory();
            Marshaller marshaller = marshallerFactory.getMarshaller(assertion);
            marshaller.marshall(assertion, document);

            Signer.signObjects(signatureList);

        } catch (CertificateEncodingException e) {
            throw new TrustException("Error in setting the signature", e);
        } catch (SignatureException e) {
            throw new TrustException("errorSigningAssertion", e);
        } catch (MarshallingException e) {
            throw new TrustException("errorMarshallingAssertion", e);
        }

        log.debug("SAML2.0 assertion is marshalled and signed..");

        return assertion;
    }

    /**
     * This method is used to create SignKeyHolder instances that contains the credentials required for signing the
     * assertion
     * @param crypto The crypto properties associated with the issuer.
     * @return  SignKeyHolder object.
     * @throws TrustException  If an error occurred while creating SignKeyHolder object.
     */
    private SignKeyHolder createSignKeyHolder(Crypto crypto) throws TrustException {

        SignKeyHolder signKeyHolder = new SignKeyHolder();

        try {
            X509Certificate[] issuerCerts = CommonUtil.getCertificatesByAlias(crypto,
                    this.tokenIssuerConfiguration.getIssuerKeyAlias());

            String sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_RSA;
            String pubKeyAlgo = issuerCerts[0].getPublicKey().getAlgorithm();
            if (pubKeyAlgo.equalsIgnoreCase("DSA")) {
                sigAlgo = XMLSignature.ALGO_ID_SIGNATURE_DSA;
            }

            java.security.Key issuerPK = crypto.getPrivateKey(
                    this.tokenIssuerConfiguration.getIssuerKeyAlias(),
                    this.tokenIssuerConfiguration.getIssuerKeyPassword());

            signKeyHolder.setIssuerCerts(issuerCerts);
            signKeyHolder.setIssuerPK((PrivateKey) issuerPK);
            signKeyHolder.setSignatureAlgorithm(sigAlgo);

        } catch (Exception e) {
            throw new TrustException("Error creating issuer signature");
        }

        log.debug("SignKeyHolder object is created with the credentials..");

        return signKeyHolder;
    }

    /**
     * This method creates an AttributeStatement. The relevant XML would look like as follows,
     * <saml:AttributeStatement>
     *    <saml:Attribute
     *      xmlns:x500="urn:oasis:names:tc:SAML:2.0:profiles:attribute:X500"
     *      x500:Encoding="LDAP"
     *      NameFormat="urn:oasis:names:tc:SAML:2.0:attrname-format:uri"
     *      Name="urn:oid:1.3.6.1.4.1.5923.1.1.1.1"
     *      FriendlyName="eduPersonAffiliation">
     *      <saml:AttributeValue
     *        xsi:type="xs:string">member</saml:AttributeValue>
     *      <saml:AttributeValue
     *        xsi:type="xs:string">staff</saml:AttributeValue>
     *    </saml:Attribute>
     *  </saml:AttributeStatement>
     *  Reference -  http://en.wikipedia.org/wiki/SAML_2.0#SAML_2.0_Assertions
     * @param data The RahasData which carry information about RST.
     * @return An AttributeStatement with filled attributes retrieved by calling callback class.
     * @throws TrustException If an error occurred while creating the AttributeStatement.
     */
    protected AttributeStatement createAttributeStatement(RahasData data) throws TrustException {


        AttributeStatement attributeStatement
                = (AttributeStatement) CommonUtil.buildXMLObject(AttributeStatement.DEFAULT_ELEMENT_NAME);

        Attribute[] attributes;

        SAMLCallbackHandler handler = CommonUtil.getSAMLCallbackHandler(this.tokenIssuerConfiguration, data);

        SAMLAttributeCallback cb = new SAMLAttributeCallback(data);
        if (handler != null) {
            try {
                handler.handle(cb);
            } catch (SAMLException e) {
                throw new TrustException(
                            "errorCallingSAMLCallback",
                            e);
            }

            attributes = cb.getSAML2Attributes();
        } else { //else add the attribute with a default value

            log.debug("No callback registered to get attributes ... Using default attributes");

            // TODO do we need to remove this ?
            Attribute attribute = (Attribute) CommonUtil.buildXMLObject(Attribute.DEFAULT_ELEMENT_NAME);
            attribute.setName("Name");
            attribute.setNameFormat("urn:oasis:names:tc:SAML:2.0:attrname-format:unspecified");

            XMLObjectBuilderFactory builderFactory = Configuration.getBuilderFactory();

            XSStringBuilder attributeValueBuilder = (XSStringBuilder) builderFactory
                    .getBuilder(XSString.TYPE_NAME);

            XSString stringValue = attributeValueBuilder.buildObject(
                    AttributeValue.DEFAULT_ELEMENT_NAME, XSString.TYPE_NAME);
            stringValue.setValue("Colombo/Rahas");
            attribute.getAttributeValues().add(stringValue);
            attributes = new Attribute[1];
            attributes[0] = attribute;
        }
        //add attributes to the attribute statement
        attributeStatement.getAttributes().addAll(Arrays.asList(attributes));

        log.debug("SAML2.0 attribute statement is constructed successfully.");

        return attributeStatement;
    }

    /**
     * This method creates an authentication statement. The equivalent XML would look as follows,
     * <saml:AuthnStatement
     *    AuthnInstant="2004-12-05T09:22:00Z"
     *    SessionIndex="b07b804c-7c29-ea16-7300-4f3d6f7928ac">
     *    <saml:AuthnContext>
     *      <saml:AuthnContextClassRef>
     *        urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport
     *     </saml:AuthnContextClassRef>
     *    </saml:AuthnContext>
     *  </saml:AuthnStatement>
     * @param data The RahasData which carry information about RST.
     * @return OpenSAML representation of an AuthnStatement class.
     * @throws TrustException If an error occurred while creating the authentication statement.
     */
    protected AuthnStatement createAuthenticationStatement(RahasData data) throws TrustException {

        MessageContext inMsgCtx = data.getInMessageContext();

        //build the auth stmt
        AuthnStatement authenticationStatement
                = (AuthnStatement)CommonUtil.buildXMLObject(AuthnStatement.DEFAULT_ELEMENT_NAME);

        // set the authn instance
        // TODO do we need to use the same time as specified in the conditions ?
        authenticationStatement.setAuthnInstant(new DateTime());

        // Create authentication context
        AuthnContext authContext = (AuthnContext)CommonUtil.buildXMLObject(AuthnContext.DEFAULT_ELEMENT_NAME);

        // Create authentication context class reference
        AuthnContextClassRef authCtxClassRef
                = (AuthnContextClassRef)CommonUtil.buildXMLObject(AuthnContextClassRef.DEFAULT_ELEMENT_NAME);
        
        //if username/password based authn
        if (inMsgCtx.getProperty(RahasConstants.USERNAME) != null) {
            authCtxClassRef.setAuthnContextClassRef(AuthnContext.PASSWORD_AUTHN_CTX);
        } else if (inMsgCtx.getProperty(RahasConstants.X509_CERT) != null) { //if X.509 cert based authn
            authCtxClassRef.setAuthnContextClassRef(AuthnContext.X509_AUTHN_CTX);
        }

        authContext.setAuthnContextClassRef(authCtxClassRef);
        authenticationStatement.setAuthnContext(authContext);

        log.debug("SAML2.0 authentication statement is constructed successfully.");

        return authenticationStatement;
    }

    /**
     * This method will set the subject principal details to the given subject.
     * @param subject The subject.
     * @param subjectNameId Subject name id, to identify the principal
     * @param format Format of the subjectNameId, i.e. email, x509subject etc ...
     * @throws TrustException If an error occurred while building NameID.
     */
    protected static void setSubjectNamedIdentifierData(Subject subject, String subjectNameId, String format)
            throws TrustException {

        //Create NameID and attach it to the subject
        NameID nameID = SAML2Utils.createNamedIdentifier(subjectNameId, format);
        subject.setNameID(nameID);
    }

    /**
     * This method creates the KeyInfo relevant for the assertion. The KeyInfo could be created in 2 ways.
     * 1. Using symmetric key - KeyInfo is created using a symmetric key
     * 2. Using a public key - KeyInfo created using a public key
     * The methodology is decided by looking at RahasData.getKeyType() method.
     * @param doc The document which we are processing.
     * @param crypto Includes crypto properties relevant to issuer.
     * @param data Includes metadata about the RST.
     * @return OpenSAML representation of KeyInfo.
     * @throws TrustException If an error occurred while creating the KeyInfo object.
     */
    protected KeyInfo createKeyInfo(Document doc, Crypto crypto, RahasData data)
            throws TrustException {

        KeyInfo keyInfo;

        // If it is a Symmetric Key
        if (data.getKeyType().endsWith(RahasConstants.KEY_TYPE_SYMM_KEY)) {

            isSymmetricKeyBasedHoK = true;
            X509Certificate serviceCert = null;
            try {

                // Get AppliesTo to figure out which service to issue the token
                // for
                serviceCert = this.tokenIssuerConfiguration.getServiceCert(crypto, data.getAppliesToAddress());

                keyInfo = CommonUtil.getSymmetricKeyBasedKeyInfo(doc, data, serviceCert, data.getKeySize(), crypto,
                        tokenIssuerConfiguration.getKeyComputation());

            } catch (Exception e) {
                if (serviceCert != null) {
                    throw new TrustException(
                            "errorInBuildingTheEncryptedKeyForPrincipal",
                            new String[]{serviceCert.getSubjectDN().getName()},
                            e);
                } else {
                    throw new TrustException(
                            "errorInBuildingTheEncryptedKeyForPrincipal",
                            new String[]{"UnknownSubjectDN"},
                            e);
                }
            }

        } else if (data.getKeyType().endsWith(RahasConstants.KEY_TYPE_PUBLIC_KEY)) {    // If it is a public Key

            try {
                // Create the ds:KeyValue element with the ds:X509Data
                X509Certificate clientCert = data.getClientCert();

                if (clientCert == null) {
                    // TODO are we always looking up by alias ? Dont we need to lookup by any other attribute ?
                    clientCert = CommonUtil.getCertificateByAlias(crypto, data.getPrincipal().getName());
                }

                keyInfo = CommonUtil.getCertificateBasedKeyInfo(clientCert);

            } catch (Exception e) {
                throw new TrustException("samlAssertionCreationError", e);
            }
        } else {
            log.error("Unidentified key type " + data.getKeyType());
            throw new TrustException(
                            "unidentifiedKeyType",
                            new String[]{data.getKeyType()});
        }

        return keyInfo;

    }

    /**
     * @inheritDoc
     */
    public String getResponseAction(RahasData data) throws TrustException {
        return null;
    }

    /**
     * @inheritDoc
     */
    public void setConfigurationFile(String configFile) {
        this.configFile = configFile;
    }

    /**
     * @inheritDoc
     */
    public void setConfigurationElement(OMElement configElement) {
        this.configElement = configElement;
    }

    /**
     * @inheritDoc
     */
    public void setConfigurationParamName(String configParamName) {
        this.configParamName = configParamName;
    }

}
