/*
 * 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.rampart.builder;

import org.apache.axiom.om.OMElement;
import org.apache.axis2.client.Options;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.rahas.EncryptedKeyToken;
import org.apache.rahas.SimpleTokenStore;
import org.apache.rahas.TrustException;
import org.apache.rampart.RampartException;
import org.apache.rampart.RampartMessageData;
import org.apache.rampart.policy.RampartPolicyData;
import org.apache.rampart.policy.SupportingPolicyData;
import org.apache.rampart.policy.model.RampartConfig;
import org.apache.rampart.util.RampartUtil;
import org.apache.ws.secpolicy.Constants;
import org.apache.ws.secpolicy.SPConstants;
import org.apache.ws.secpolicy.model.AlgorithmSuite;
import org.apache.ws.secpolicy.model.IssuedToken;
import org.apache.ws.secpolicy.model.SecureConversationToken;
import org.apache.ws.secpolicy.model.SupportingToken;
import org.apache.ws.secpolicy.model.Token;
import org.apache.ws.secpolicy.model.UsernameToken;
import org.apache.ws.secpolicy.model.X509Token;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSEncryptionPart;
import org.apache.ws.security.WSPasswordCallback;
import org.apache.ws.security.WSSecurityEngineResult;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.conversation.ConversationConstants;
import org.apache.ws.security.conversation.ConversationException;
import org.apache.ws.security.handler.WSHandlerConstants;
import org.apache.ws.security.handler.WSHandlerResult;
import org.apache.ws.security.message.WSSecDKSign;
import org.apache.ws.security.message.WSSecEncryptedKey;
import org.apache.ws.security.message.WSSecSignature;
import org.apache.ws.security.message.WSSecSignatureConfirmation;
import org.apache.ws.security.message.WSSecTimestamp;
import org.apache.ws.security.message.WSSecUsernameToken;
import org.apache.ws.security.message.token.SecurityTokenReference;
import org.apache.ws.security.util.WSSecurityUtil;
import org.w3c.dom.Document;
import org.w3c.dom.Element;

import javax.security.auth.callback.CallbackHandler;
import javax.security.auth.callback.UnsupportedCallbackException;
import javax.xml.crypto.dsig.Reference;

import java.io.IOException;
import java.util.*;
import java.util.Map.Entry;

public abstract class BindingBuilder {
    private static Log log = LogFactory.getLog(BindingBuilder.class);

    private Element insertionLocation;
    
    protected String mainSigId = null;
    
    protected ArrayList<String> encryptedTokensIdList = new ArrayList<String>();
    
    protected Element timestampElement;
    
    protected Element mainRefListElement;
    
    
    /**
     * @param rmd
     */
    protected void addTimestamp(RampartMessageData rmd) {
        log.debug("Adding timestamp");

        WSSecTimestamp timestampBuilder = new WSSecTimestamp();
        timestampBuilder.setWsConfig(rmd.getConfig());

        timestampBuilder.setTimeToLive(RampartUtil.getTimeToLive(rmd));
        
        // add the Timestamp to the SOAP Enevelope

        timestampBuilder.build(rmd.getDocument(), rmd
                .getSecHeader());

        if (log.isDebugEnabled()) {
            log.debug("Timestamp id: " + timestampBuilder.getId());
        }
        rmd.setTimestampId(timestampBuilder.getId());
        
        this.timestampElement = timestampBuilder.getElement();
        log.debug("Adding timestamp: DONE");
    }
    
    /**
     * Add a UsernameToken to the security header
     * @param rmd
     * @return The <code>WSSecUsernameToken</code> instance
     * @throws RampartException
     */
    protected WSSecUsernameToken addUsernameToken(RampartMessageData rmd, UsernameToken token) throws RampartException {

        log.debug("Adding a UsernameToken");

        RampartPolicyData rpd = rmd.getPolicyData();
        
        //Get the user
        //First try options
        Options options = rmd.getMsgContext().getOptions();
        String user = options.getUserName();
        if(user == null || user.length() == 0) {
            //Then try RampartConfig
            if(rpd.getRampartConfig() != null) {
                user = rpd.getRampartConfig().getUser();
            }
        }
        
        if(user != null && !"".equals(user)) {
            if (log.isDebugEnabled()) {
                log.debug("User : " + user);
            }

            // If NoPassword property is set we don't need to set the password
            if (token.isNoPassword()) {
                WSSecUsernameToken utBuilder = new WSSecUsernameToken();
                utBuilder.setUserInfo(user, null);
                utBuilder.setPasswordType(null);
                if (rmd.getConfig() != null) {
                    utBuilder.setWsConfig(rmd.getConfig());
                }
                return utBuilder;
            }
            
            //Get the password

            //First check options object for a password
            String password = options.getPassword();
            
            if(password == null || password.length() == 0) {
                
                //Then try to get the password from the given callback handler
                CallbackHandler handler = RampartUtil.getPasswordCB(rmd);
            
                if(handler == null) {
                    //If the callback handler is missing
                    throw new RampartException("cbHandlerMissing");
                }
                
                WSPasswordCallback[] cb = { new WSPasswordCallback(user,
                        WSPasswordCallback.USERNAME_TOKEN) };
                try {
                    handler.handle(cb);
                } catch (Exception e) {
                    throw new RampartException("errorInGettingPasswordForUser", 
                            new String[]{user}, e);
                }
                
                //get the password
                password = cb[0].getPassword();
            }

            if(password != null && !"".equals(password)) {
                //If the password is available then build the token
                
                WSSecUsernameToken utBuilder = new WSSecUsernameToken();
                if(rmd.getConfig() != null) {
                    utBuilder.setWsConfig(rmd.getConfig());
                }
                if (token.isHashPassword()) {
                    utBuilder.setPasswordType(WSConstants.PASSWORD_DIGEST);  
                } else {
                    utBuilder.setPasswordType(WSConstants.PASSWORD_TEXT);
                }
                
                utBuilder.setUserInfo(user, password);
                
                return utBuilder;
            } else {
                //If there's no password then throw an exception
                throw new RampartException("noPasswordForUser", 
                        new String[]{user});
            }
            
        } else {
            log.debug("No user value specified in the configuration");
            throw new RampartException("userMissing");
        }
        
    }
    
    
    /**
     * @param rmd
     * @param token
     * @return
     * @throws WSSecurityException
     * @throws RampartException
     */
    protected WSSecEncryptedKey getEncryptedKeyBuilder(RampartMessageData rmd, Token token) throws RampartException {
        
        RampartPolicyData rpd = rmd.getPolicyData();
        Document doc = rmd.getDocument();
        
        WSSecEncryptedKey encrKey = new WSSecEncryptedKey();
        
        try {
            RampartUtil.setKeyIdentifierType(rmd, encrKey, token);
            RampartUtil.setEncryptionUser(rmd, encrKey);

            //TODO we do not need to pass keysize as it is taken from algorithm it self - verify
            encrKey.setKeyEncAlgo(rpd.getAlgorithmSuite().getAsymmetricKeyWrap());
            
            encrKey.prepare(doc, RampartUtil.getEncryptionCrypto(rpd.getRampartConfig(), rmd.getCustomClassLoader()));
            
            return encrKey;
        } catch (WSSecurityException e) {
            throw new RampartException("errorCreatingEncryptedKey", e);
        }
    }
    
    //Deprecated after 1.5 release
    @Deprecated 
    protected WSSecSignature getSignatureBuider(RampartMessageData rmd, 
                                                Token token) throws RampartException {
    	return getSignatureBuilder(rmd, token, null);
    }

    //Deprecated after 1.5 release
    @Deprecated
    protected WSSecSignature getSignatureBuider(RampartMessageData rmd, Token token,
                                                String userCertAlias) throws RampartException {
    	return getSignatureBuilder(rmd, token, userCertAlias);
    }
    
    protected WSSecSignature getSignatureBuilder(RampartMessageData rmd, 
                                                 Token token)throws RampartException {
        return getSignatureBuilder(rmd, token, null);
    }
    
    protected WSSecSignature getSignatureBuilder(RampartMessageData rmd, Token token,
                                                 String userCertAlias) throws RampartException {

        RampartPolicyData rpd = rmd.getPolicyData();
        
        WSSecSignature sig = new WSSecSignature();
        checkForX509PkiPath(sig, token);
        sig.setWsConfig(rmd.getConfig());

        if (log.isDebugEnabled()) {
            log.debug("Token inclusion: " + token.getInclusion());
        }

        RampartUtil.setKeyIdentifierType(rmd, sig, token);

        String user = null;
        
        if (userCertAlias != null) {
            user = userCertAlias;
        }

        // Get the user - First check whether userCertAlias present
        RampartConfig rampartConfig = rpd.getRampartConfig();
        if(rampartConfig == null) {
        	throw new RampartException("rampartConfigMissing");
        }
        
		if (user == null) {
            user = rampartConfig.getUserCertAlias();
        }
        
        // If userCertAlias is not present, use user property as Alias
        
        if (user == null) {
            user = rampartConfig.getUser();
        }
            
        String password = null;

        if(user != null && !"".equals(user)) {
            if (log.isDebugEnabled()) {
                log.debug("User : " + user);
            }

            //Get the password
            CallbackHandler handler = RampartUtil.getPasswordCB(rmd);
            
            if(handler == null) {
                //If the callback handler is missing
                throw new RampartException("cbHandlerMissing");
            }
            
            WSPasswordCallback[] cb = { new WSPasswordCallback(user,
                    WSPasswordCallback.SIGNATURE) };
            
            try {
                handler.handle(cb);
                if(cb[0].getPassword() != null && !"".equals(cb[0].getPassword())) {
                    password = cb[0].getPassword();
                    if (log.isDebugEnabled()) {
                        log.debug("Password : " + password);
                    }
                } else {
                    //If there's no password then throw an exception
                    throw new RampartException("noPasswordForUser", 
                            new String[]{user});
                }
            } catch (IOException e) {
                throw new RampartException("errorInGettingPasswordForUser", 
                        new String[]{user}, e);
            } catch (UnsupportedCallbackException e) {
                throw new RampartException("errorInGettingPasswordForUser", 
                        new String[]{user}, e);
            }
            
        } else {
            log.debug("No user value specified in the configuration");
            throw new RampartException("userMissing");
        }
        
        sig.setUserInfo(user, password);
        AlgorithmSuite algorithmSuite = rpd.getAlgorithmSuite();
		sig.setSignatureAlgorithm(algorithmSuite.getAsymmetricSignature());
        sig.setSigCanonicalization(algorithmSuite.getInclusiveC14n());
        sig.setDigestAlgo(algorithmSuite.getDigest());

        try {
            sig.prepare(rmd.getDocument(), RampartUtil.getSignatureCrypto(rampartConfig, rmd.getCustomClassLoader()), 
                    rmd.getSecHeader());
        } catch (WSSecurityException e) {
            throw new RampartException("errorInSignatureWithX509Token", e);
        }
        
        return sig;
    }
    
    /**
     * @param rmd
     * @param suppTokens
     * @throws RampartException
     */
    protected HashMap handleSupportingTokens(RampartMessageData rmd, SupportingToken suppTokens)
            throws RampartException {
        
        //Create the list to hold the tokens
        // TODO putting different types of objects. Need to figure out a way to add single types of objects
        HashMap endSuppTokMap = new HashMap();
        
        if(suppTokens != null && suppTokens.getTokens() != null &&
                suppTokens.getTokens().size() > 0) {
            log.debug("Processing supporting tokens");

            ArrayList tokens = suppTokens.getTokens();
            for (Object objectToken : tokens) {
                Token token = (Token) objectToken;
                org.apache.rahas.Token endSuppTok = null;
                if (token instanceof IssuedToken && rmd.isInitiator()) {
                    String id = RampartUtil.getIssuedToken(rmd, (IssuedToken) token);
                    try {
                        endSuppTok = rmd.getTokenStorage().getToken(id);
                    } catch (TrustException e) {
                        throw new RampartException("errorInRetrievingTokenId",
                                new String[]{id}, e);
                    }

                    if (endSuppTok == null) {
                        throw new RampartException("errorInRetrievingTokenId",
                                new String[]{id});
                    }

                    //Add the token to the header
                    Element siblingElem = RampartUtil
                            .insertSiblingAfter(rmd, this.getInsertionLocation(),
                                    (Element) endSuppTok.getToken());
                    this.setInsertionLocation(siblingElem);

                    if (suppTokens.isEncryptedToken()) {
                        this.encryptedTokensIdList.add(endSuppTok.getId());
                    }

                    //Add the extracted token
                    endSuppTokMap.put(token, endSuppTok);

                } else if (token instanceof X509Token) {

                    //We have to use a cert
                    //Prepare X509 signature
                    WSSecSignature sig = this.getSignatureBuilder(rmd, token);
                    Element bstElem = sig.getBinarySecurityTokenElement();
                    if (bstElem != null) {
                        bstElem = RampartUtil.insertSiblingAfter(rmd,
                                this.getInsertionLocation(), bstElem);
                        this.setInsertionLocation(bstElem);

                        SupportingPolicyData supportingPolcy = new SupportingPolicyData();
                        supportingPolcy.build(suppTokens);
                        supportingPolcy.setSignatureToken(token);
                        supportingPolcy.setEncryptionToken(token);
                        rmd.getPolicyData().addSupportingPolicyData(supportingPolcy);

                        if (suppTokens.isEncryptedToken()) {
                            this.encryptedTokensIdList.add(sig.getBSTTokenId());
                        }
                    }
                    endSuppTokMap.put(token, sig);

                } else if (token instanceof UsernameToken) {
                    WSSecUsernameToken utBuilder = addUsernameToken(rmd, (UsernameToken) token);

                    utBuilder.prepare(rmd.getDocument());

                    //Add the UT
                    Element elem = utBuilder.getUsernameTokenElement();
                    elem = RampartUtil.insertSiblingAfter(rmd, this.getInsertionLocation(), elem);

                    encryptedTokensIdList.add(utBuilder.getId());

                    //Move the insert location to the next element
                    this.setInsertionLocation(elem);
                    Date now = new Date();
                    try {
                        org.apache.rahas.Token tempTok = new org.apache.rahas.Token(
                                utBuilder.getId(), (OMElement) elem, now,
                                new Date(now.getTime() + 300000));
                        endSuppTokMap.put(token, tempTok);
                    } catch (TrustException e) {
                        throw new RampartException("errorCreatingRahasToken", e);
                    }
                }
            }
        }
        
        return endSuppTokMap;
    }
    /**
     * @param tokenMap
     * @param sigParts
     * @throws RampartException
     */
    protected List<WSEncryptionPart> addSignatureParts(HashMap tokenMap, List<WSEncryptionPart> sigParts)
            throws RampartException {
    	
        Set entrySet = tokenMap.entrySet();

        for (Object anEntrySet : entrySet) {
            Object tempTok = ((Entry) anEntrySet).getValue();
            WSEncryptionPart part = null;

            if (tempTok instanceof org.apache.rahas.Token) {

                part = new WSEncryptionPart(
                        ((org.apache.rahas.Token) tempTok).getId());

            } else if (tempTok instanceof WSSecSignature) {
                WSSecSignature tempSig = (WSSecSignature) tempTok;
                if (tempSig.getBSTTokenId() != null) {
                    part = new WSEncryptionPart(tempSig.getBSTTokenId());
                }
            } else {

                throw new RampartException("UnsupportedTokenInSupportingToken");
            }
            sigParts.add(part);
        }
                
        return sigParts;
    }

    
    public Element getInsertionLocation() {
        return insertionLocation;
    }

    public void setInsertionLocation(Element insertionLocation) {
        this.insertionLocation = insertionLocation;
    }
    
    
    protected List<byte[]> doEndorsedSignatures(RampartMessageData rmd, HashMap tokenMap) throws RampartException {
        
        Set tokenSet = tokenMap.keySet();
        
        List<byte[]> sigValues = new ArrayList<byte[]>();

        for (Object aTokenSet : tokenSet) {

            Token token = (Token) aTokenSet;

            Object tempTok = tokenMap.get(token);

            // Migrating to a list
            List<WSEncryptionPart> sigParts = new ArrayList<WSEncryptionPart>();
            sigParts.add(new WSEncryptionPart(this.mainSigId));

            if (tempTok instanceof org.apache.rahas.Token) {
                org.apache.rahas.Token tok = (org.apache.rahas.Token) tempTok;
                if (rmd.getPolicyData().isTokenProtection()) {
                    sigParts.add(new WSEncryptionPart(tok.getId()));
                }

                this.doSymmSignature(rmd, token, (org.apache.rahas.Token) tempTok, sigParts);

            } else if (tempTok instanceof WSSecSignature) {
                WSSecSignature sig = (WSSecSignature) tempTok;
                if (rmd.getPolicyData().isTokenProtection() &&
                        sig.getBSTTokenId() != null) {
                    sigParts.add(new WSEncryptionPart(sig.getBSTTokenId()));
                }

                try {


                    List<Reference> referenceList
                            = sig.addReferencesToSign(sigParts, rmd.getSecHeader());

                    /**
                     * Before migration it was - this.setInsertionLocation(RampartUtil.insertSiblingAfter(rmd, this
                     *       .getInsertionLocation(), supportingSignatureElement));
                     *
                     * In this case we need to append <Signature>..</Signature> element to
                     * current insertion location
                     */

                    sig.computeSignature(referenceList, false, this.getInsertionLocation());

                    this.setInsertionLocation(sig.getSignatureElement());

                } catch (WSSecurityException e) {
                    throw new RampartException("errorInSignatureWithX509Token", e);
                }
                sigValues.add(sig.getSignatureValue());
            }
        } 

        return sigValues;
            
    }
    
    
    protected byte[] doSymmSignature(RampartMessageData rmd, Token policyToken, org.apache.rahas.Token tok,
                                     List<WSEncryptionPart> sigParts) throws RampartException {
        
        Document doc = rmd.getDocument();
        
        RampartPolicyData rpd = rmd.getPolicyData();
        
        AlgorithmSuite algorithmSuite = rpd.getAlgorithmSuite();
		if(policyToken.isDerivedKeys()) {
            try {
                WSSecDKSign dkSign = new WSSecDKSign();  
                
                //Check whether it is security policy 1.2 and use the secure conversation accordingly
                if (SPConstants.SP_V12 == policyToken.getVersion()) {
                    dkSign.setWscVersion(ConversationConstants.VERSION_05_12);
                }
                              
                //Check for whether the token is attached in the message or not
                boolean attached = false;
                
                if (SPConstants.INCLUDE_TOEKN_ALWAYS == policyToken.getInclusion() ||
                    SPConstants.INCLUDE_TOKEN_ONCE == policyToken.getInclusion() ||
                    (rmd.isInitiator() && SPConstants.INCLUDE_TOEKN_ALWAYS_TO_RECIPIENT 
                            == policyToken.getInclusion())) {
                    attached = true;
                }
                
                // Setting the AttachedReference or the UnattachedReference according to the flag
                OMElement ref;
                if (attached) {
                    ref = tok.getAttachedReference();
                } else {
                    ref = tok.getUnattachedReference();
                }
                
                if(ref != null) {
                    dkSign.setExternalKey(tok.getSecret(), (Element) 
                            doc.importNode((Element) ref, true));
                } else if (!rmd.isInitiator() && policyToken.isDerivedKeys()) { 
                	
                	// If the Encrypted key used to create the derived key is not
                	// attached use key identifier as defined in WSS1.1 section
                	// 7.7 Encrypted Key reference
                	SecurityTokenReference tokenRef = new SecurityTokenReference(doc);
                	if(tok instanceof EncryptedKeyToken) {
                	    tokenRef.setKeyIdentifierEncKeySHA1(((EncryptedKeyToken)tok).getSHA1());;
                	}
                	dkSign.setExternalKey(tok.getSecret(), tokenRef.getElement());
                    tokenRef.addTokenType(WSConstants.WSS_ENC_KEY_VALUE_TYPE);  // TODO check this
                
                } else {
                    dkSign.setExternalKey(tok.getSecret(), tok.getId());
                }

                //Set the algo info
                dkSign.setSignatureAlgorithm(algorithmSuite.getSymmetricSignature());
                dkSign.setDerivedKeyLength(algorithmSuite.getSignatureDerivedKeyLength()/8);
//                dkSign.setDigestAlgorithm(algorithmSuite.getDigest()); //uncomment when wss4j version is updated
                if(tok instanceof EncryptedKeyToken) {
                    //Set the value type of the reference
                    dkSign.setCustomValueType(WSConstants.SOAPMESSAGE_NS11 + "#"
                        + WSConstants.ENC_KEY_VALUE_TYPE);
                }
                
                dkSign.prepare(doc, rmd.getSecHeader());
                
                if(rpd.isTokenProtection()) {

                    //Hack to handle reference id issues
                    //TODO Need a better fix
                    String sigTokId = tok.getId();
                    if(sigTokId.startsWith("#")) {
                        sigTokId = sigTokId.substring(1);
                    }
                    sigParts.add(new WSEncryptionPart(sigTokId));
                }
                
                dkSign.setParts(sigParts);
                
                List<Reference> referenceList
                        = dkSign.addReferencesToSign(sigParts, rmd.getSecHeader());

                //Add elements to header
                //Do signature
                if (rpd.getProtectionOrder().equals(SPConstants.ENCRYPT_BEFORE_SIGNING) &&
                        this.mainRefListElement != null ) {

                     /**
                     * <xenc:ReferenceList>
                     *     <xenc:DataReference URI="#EncDataId-2"/>
                     * </xenc:ReferenceList>
                     * If there is a reference list as above we need to first prepend reference list
                     * with the new derived key. Then we need to prepend Signature to newly added derived key.
                     */

                    // Add DeriveKey before ReferenceList
                    RampartUtil.insertSiblingBefore(rmd, this.mainRefListElement, dkSign.getdktElement());

                    // Insert signature before DerivedKey
                    dkSign.computeSignature(referenceList, true, dkSign.getdktElement());
                    this.setInsertionLocation(this.mainRefListElement);
                } else {

                    /**
                     * Add <wsc:DerivedKeyToken>..</wsc:DerivedKeyToken> to security
                     * header.
                     */
                    dkSign.appendDKElementToHeader(rmd.getSecHeader());

                    this.setInsertionLocation(dkSign.getdktElement());

                    /**
                     * In this case we need to insert <Signature>..</Signature> element
                     * before this.mainRefListElement element. In other words we need to
                     * prepend <Signature>...</Signature> element to this.mainRefListElement.
                     */
                    dkSign.computeSignature(referenceList, false, this.getInsertionLocation());
                    this.setInsertionLocation(dkSign.getSignatureElement());
                }

                return dkSign.getSignatureValue();
                
            } catch (ConversationException e) {
                throw new RampartException(
                        "errorInDerivedKeyTokenSignature", e);
            } catch (WSSecurityException e) {
                throw new RampartException(
                        "errorInDerivedKeyTokenSignature", e);
            }
        } else {
            try {
                WSSecSignature sig = new WSSecSignature();
                sig.setWsConfig(rmd.getConfig());
                
                // If a EncryptedKeyToken is used, set the correct value type to
                // be used in the wsse:Reference in ds:KeyInfo
                if (policyToken instanceof X509Token) {
                    if (rmd.isInitiator()) {
                        sig.setCustomTokenValueType(WSConstants.SOAPMESSAGE_NS11 + "#"
                                + WSConstants.ENC_KEY_VALUE_TYPE);
                        sig.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);
                    } else {
                        // the tok has to be an EncryptedKey token
                        sig.setEncrKeySha1value(((EncryptedKeyToken) tok).getSHA1());
                        sig.setKeyIdentifierType(WSConstants.ENCRYPTED_KEY_SHA1_IDENTIFIER);
                    }

                } else if (policyToken instanceof IssuedToken) {

                    sig.setCustomTokenValueType(RampartUtil.getSAML10AssertionNamespace());
                    sig.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);
                }
                
                String sigTokId; 
                
                if ( policyToken instanceof SecureConversationToken) {
                    sig.setKeyIdentifierType(WSConstants.CUSTOM_SYMM_SIGNING);
                    OMElement ref = tok.getAttachedReference();
                    if(ref == null) {
                        ref = tok.getUnattachedReference();
                    }
                    
                    if (ref != null) {
                        sigTokId = SimpleTokenStore.getIdFromSTR(ref);
                    } else {
                        sigTokId = tok.getId();
                    }
                } else {
                    sigTokId = tok.getId();
                }
                               
                //Hack to handle reference id issues
                //TODO Need a better fix
                if(sigTokId.startsWith("#")) {
                    sigTokId = sigTokId.substring(1);
                }
                
                sig.setCustomTokenId(sigTokId);
                sig.setSecretKey(tok.getSecret());
                sig.setSignatureAlgorithm(algorithmSuite.getAsymmetricSignature()); // TODO what is the correct algorith ? For sure one is redundant
                sig.setSignatureAlgorithm(algorithmSuite.getSymmetricSignature());
                sig.setDigestAlgo(algorithmSuite.getDigest());
                sig.prepare(rmd.getDocument(), RampartUtil.getSignatureCrypto(rpd
                        .getRampartConfig(), rmd.getCustomClassLoader()),
                        rmd.getSecHeader());

                sig.setParts(sigParts);
                List<Reference> referenceList
                        = sig.addReferencesToSign(sigParts, rmd.getSecHeader());

                //Do signature
                if (rpd.getProtectionOrder().equals(SPConstants.ENCRYPT_BEFORE_SIGNING)
                        && this.mainRefListElement != null) {

                    /**
                     * In this case we need to insert <Signature>..</Signature> element
                     * before this.mainRefListElement element. In other words we need to
                     * prepend <Signature>...</Signature> element to this.mainRefListElement.
                     * this.mainRefListElement is equivalent to
                     * <xenc:ReferenceList>
                     *     <xenc:DataReference URI="#EncDataId-2"/>
                     * </xenc:ReferenceList>
                     */
                    sig.computeSignature(referenceList, true, this.mainRefListElement);
                    this.setInsertionLocation(this.mainRefListElement);
                } else {

                    /**
                     * In this case we need to append <Signature>..</Signature> element to
                     * current insertion location.
                     */
                    sig.computeSignature(referenceList, false, this.getInsertionLocation());
                    this.setInsertionLocation(sig.getSignatureElement());
                }


                return sig.getSignatureValue();
                
            } catch (WSSecurityException e) {
                throw new RampartException("errorInSignatureWithACustomToken", e);
            }

        }
    }
    
    
    /**
     * Get hold of the token from the token storage
     * @param rmd
     * @param tokenId
     * @return token from the token storage
     * @throws RampartException
     */
    protected org.apache.rahas.Token getToken(RampartMessageData rmd, 
                    String tokenId) throws RampartException {
        org.apache.rahas.Token tok;
        try {
            tok = rmd.getTokenStorage().getToken(tokenId);
        } catch (TrustException e) {
            throw new RampartException("errorInRetrievingTokenId", 
                    new String[]{tokenId}, e);
        }
        
        if(tok == null) {
            throw new RampartException("errorInRetrievingTokenId", 
                    new String[]{tokenId});
        }
        return tok;
    }
    

    protected void addSignatureConfirmation(RampartMessageData rmd, List<WSEncryptionPart> sigParts) {
        
        if(!rmd.getPolicyData().isSignatureConfirmation()) {
            
            //If we don't require sig confirmation simply go back :-)
            return;
        }
        
        Document doc = rmd.getDocument();

        List<WSHandlerResult> results
                = (List<WSHandlerResult>)rmd.getMsgContext().getProperty(WSHandlerConstants.RECV_RESULTS);
        /*
         * loop over all results gathered by all handlers in the chain. For each
         * handler result get the various actions. After that loop we have all
         * signature results in the signatureActions list.
         */
        List<WSSecurityEngineResult> signatureActions = new ArrayList<WSSecurityEngineResult>();
        for (Object result : results) {
            WSHandlerResult wshResult = (WSHandlerResult) result;

            WSSecurityUtil.fetchAllActionResults(wshResult.getResults(),
                    WSConstants.SIGN, signatureActions);
            WSSecurityUtil.fetchAllActionResults(wshResult.getResults(),
                    WSConstants.ST_SIGNED, signatureActions);
            WSSecurityUtil.fetchAllActionResults(wshResult.getResults(),
                    WSConstants.UT_SIGN, signatureActions);
        }
        
        // prepare a SignatureConfirmation token
        WSSecSignatureConfirmation wsc = new WSSecSignatureConfirmation();
        if (signatureActions.size() > 0) {
            if (log.isDebugEnabled()) {
                log.debug("Signature Confirmation: number of Signature results: "
                        + signatureActions.size());
            }
            for (WSSecurityEngineResult signatureAction : signatureActions) {
                byte[] sigVal = (byte[]) signatureAction.get(WSSecurityEngineResult.TAG_SIGNATURE_VALUE);
                wsc.setSignatureValue(sigVal);
                wsc.prepare(doc);
                RampartUtil.appendChildToSecHeader(rmd, wsc.getSignatureConfirmationElement());
                if (sigParts != null) {
                    sigParts.add(new WSEncryptionPart(wsc.getId()));
                }
            }
        } else {
            //No Sig value
            wsc.prepare(doc);
            RampartUtil.appendChildToSecHeader(rmd, wsc.getSignatureConfirmationElement());
            if(sigParts != null) {
                sigParts.add(new WSEncryptionPart(wsc.getId()));
            }
        }
    }
    private void checkForX509PkiPath(WSSecSignature sig, Token token){
        if (token instanceof X509Token) {
            X509Token x509Token = (X509Token) token;
            if (x509Token.getTokenVersionAndType().equals(Constants.WSS_X509_PKI_PATH_V1_TOKEN10)
                    || x509Token.getTokenVersionAndType().equals(Constants.WSS_X509_PKI_PATH_V1_TOKEN11)) {
                sig.setUseSingleCertificate(false);
            }
        }
    }

    
}
