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

import org.apache.axiom.om.OMAbstractFactory;
import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMFactory;
import org.apache.axiom.om.OMNamespace;
import org.apache.axiom.om.xpath.AXIOMXPath;
import org.apache.axiom.soap.*;
import org.apache.axis2.AxisFault;
import org.apache.axis2.addressing.AddressingConstants;
import org.apache.axis2.client.Options;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.dataretrieval.DRConstants;
import org.apache.axis2.dataretrieval.client.MexClient;
import org.apache.axis2.description.Parameter;
import org.apache.axis2.mex.MexConstants;
import org.apache.axis2.mex.MexException;
import org.apache.axis2.mex.om.Metadata;
import org.apache.axis2.mex.om.MetadataReference;
import org.apache.axis2.mex.om.MetadataSection;
import org.apache.axis2.transport.http.HTTPConstants;
import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.neethi.Policy;
import org.apache.neethi.PolicyEngine;
import org.apache.rahas.RahasConstants;
import org.apache.rahas.Token;
import org.apache.rahas.TrustException;
import org.apache.rahas.TrustUtil;
import org.apache.rahas.client.STSClient;
import org.apache.rampart.PolicyBasedResultsValidator;
import org.apache.rampart.PolicyValidatorCallbackHandler;
import org.apache.rampart.RampartConfigCallbackHandler;
import org.apache.rampart.RampartConstants;
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.CryptoConfig;
import org.apache.rampart.policy.model.RampartConfig;
import org.apache.ws.secpolicy.SPConstants;
import org.apache.ws.secpolicy.model.*;
import org.apache.ws.security.WSConstants;
import org.apache.ws.security.WSEncryptionPart;
import org.apache.ws.security.WSPasswordCallback;
import org.apache.ws.security.WSSConfig;
import org.apache.ws.security.WSSecurityEngineResult;
import org.apache.ws.security.WSSecurityException;
import org.apache.ws.security.WSUsernameTokenPrincipal;
import org.apache.ws.security.components.crypto.Crypto;
import org.apache.ws.security.components.crypto.CryptoFactory;
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.WSSecBase;
import org.apache.ws.security.message.WSSecEncryptedKey;
import org.apache.ws.security.util.Loader;
import org.apache.ws.security.util.WSSecurityUtil;
import org.apache.xml.security.utils.Constants;
import org.jaxen.JaxenException;
import org.jaxen.XPath;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;

import javax.crypto.KeyGenerator;
import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;
import javax.xml.namespace.QName;
import javax.servlet.http.HttpServletRequest;

import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

public class RampartUtil {

    private static final String CRYPTO_PROVIDER = "org.apache.ws.security.crypto.provider";
    private static Log log = LogFactory.getLog(RampartUtil.class);

    private static Map<String, CachedCrypto> cryptoStore = new ConcurrentHashMap<String, CachedCrypto>();

    private static class CachedCrypto {
        private Crypto crypto;
        private long creationTime;

        public CachedCrypto(Crypto crypto, long creationTime) {
            this.crypto = crypto;
            this.creationTime = creationTime;
        }
    }

    public static CallbackHandler getPasswordCB(RampartMessageData rmd) throws RampartException {

        MessageContext msgContext = rmd.getMsgContext();
        RampartPolicyData rpd = rmd.getPolicyData();
        
        return getPasswordCB(msgContext, rpd);
    }

    /**
     * @param msgContext
     * @param rpd
     * @return The <code>CallbackHandler</code> instance
     * @throws RampartException
     */
    public static CallbackHandler getPasswordCB(MessageContext msgContext, RampartPolicyData rpd) throws RampartException {
        
        CallbackHandler cbHandler;

        if (rpd.getRampartConfig() != null && rpd.getRampartConfig().getPwCbClass() != null) {
            
            String cbHandlerClass = rpd.getRampartConfig().getPwCbClass();
            ClassLoader classLoader = msgContext.getAxisService().getClassLoader();

            if (log.isDebugEnabled()) {
                log.debug("loading class : " + cbHandlerClass);
            }

            Class cbClass;
            try {
                cbClass = Loader.loadClass(classLoader, cbHandlerClass);
            } catch (ClassNotFoundException e) {
                throw new RampartException("cannotLoadPWCBClass", 
                        new String[]{cbHandlerClass}, e);
            }
            try {
                cbHandler = (CallbackHandler) cbClass.newInstance();
            } catch (java.lang.Exception e) {
                throw new RampartException("cannotCreatePWCBInstance",
                        new String[]{cbHandlerClass}, e);
            }
        } else {
            cbHandler = (CallbackHandler) msgContext.getProperty(
                    WSHandlerConstants.PW_CALLBACK_REF);
            if(cbHandler == null) {
                Parameter param = msgContext.getParameter(
                        WSHandlerConstants.PW_CALLBACK_REF);
                if(param != null) {
                    cbHandler = (CallbackHandler)param.getValue();
                }
            }
        }
        
        return cbHandler;
    }
    
   /**
    * Returns an instance of PolicyValidatorCallbackHandler to be used to validate ws-security results.
    * 
    * @param msgContext {@link MessageContext}
    * @param rpd {@link RampartPolicyData}
    * @return {@link PolicyValidatorCallbackHandler}
    * @throws RampartException RampartException
    */ 
   public static PolicyValidatorCallbackHandler getPolicyValidatorCB(MessageContext msgContext, RampartPolicyData rpd) throws RampartException {
        
       PolicyValidatorCallbackHandler cbHandler;

        if (rpd.getRampartConfig() != null && rpd.getRampartConfig().getPolicyValidatorCbClass() != null) {
            
            String cbHandlerClass = rpd.getRampartConfig().getPolicyValidatorCbClass();
            ClassLoader classLoader = msgContext.getAxisService().getClassLoader();

            if (log.isDebugEnabled()) {
                log.debug("loading class : " + cbHandlerClass);
            }

            Class cbClass;
            try {
                cbClass = Loader.loadClass(classLoader, cbHandlerClass);
            } catch (ClassNotFoundException e) { 
                throw new RampartException("cannotLoadPolicyValidatorCbClass", 
                        new String[]{cbHandlerClass}, e);
            }
            try {
                cbHandler = (PolicyValidatorCallbackHandler) cbClass.newInstance();
            } catch (java.lang.Exception e) {
                throw new RampartException("cannotCreatePolicyValidatorCallbackInstance",
                        new String[]{cbHandlerClass}, e);
            }
            
        } else { // Initialise default PolicyValidatorCallbackHandler...
            cbHandler = new PolicyBasedResultsValidator();
        }
        
        return cbHandler;
    }
   
   public static RampartConfigCallbackHandler getRampartConfigCallbackHandler(MessageContext msgContext, 
           RampartPolicyData rpd) throws RampartException {
       
       RampartConfigCallbackHandler rampartConfigCB;
   
       if (rpd.getRampartConfig() != null && rpd.getRampartConfig().getRampartConfigCbClass() != null) {
           
           String cbHandlerClass = rpd.getRampartConfig().getRampartConfigCbClass();
           ClassLoader classLoader = msgContext.getAxisService().getClassLoader();

           if (log.isDebugEnabled()) {
               log.debug("loading class : " + cbHandlerClass);
           }

           Class cbClass;
           try {
               cbClass = Loader.loadClass(classLoader, cbHandlerClass);
           } catch (ClassNotFoundException e) {
               throw new RampartException("cannotLoadRampartConfigCallbackClass", 
                       new String[]{cbHandlerClass}, e);
           }
           try {
               rampartConfigCB = (RampartConfigCallbackHandler) cbClass.newInstance();
           } catch (java.lang.Exception e) {
               throw new RampartException("cannotCreateRampartConfigCallbackInstance",
                       new String[]{cbHandlerClass}, e);
           }
           
           return rampartConfigCB;
           
       }
       
       return null;
   }

    /**
     * Perform a callback to get a password.
     * <p/>
     * The called back function gets an indication why to provide a password:
     * to produce a UsernameToken, Signature, or a password (key) for a given
     * name.
     */
    public static WSPasswordCallback performCallback(CallbackHandler cbHandler,
                                               String username,
                                               int doAction)
            throws RampartException {

        WSPasswordCallback pwCb;
        int reason = 0;

        switch (doAction) {
        case WSConstants.UT:
        case WSConstants.UT_SIGN:
                reason = WSPasswordCallback.USERNAME_TOKEN;
                break;
            case WSConstants.SIGN:
                reason = WSPasswordCallback.SIGNATURE;
                break;
            case WSConstants.ENCR:
                reason = WSPasswordCallback.KEY_NAME;
                break;
        }
        pwCb = new WSPasswordCallback(username, reason);
        Callback[] callbacks = new Callback[1];
        callbacks[0] = pwCb;
        /*
        * Call back the application to get the password
        */
        try {
            cbHandler.handle(callbacks);
        } catch (Exception e) {
            throw new RampartException("pwcbFailed", e);
        }
        return pwCb;
    }
    
    /**
     * Create the <code>Crypto</code> instance for encryption using information 
     * from the rampart configuration assertion
     * 
     * @param config
     * @return The <code>Crypto</code> instance to be used for encryption
     * @throws RampartException
     */
    public static Crypto getEncryptionCrypto(RampartConfig config, ClassLoader loader)
            throws RampartException {

        log.debug("Loading encryption crypto");

        Crypto crypto = null;

        if (config != null && config.getEncrCryptoConfig() != null) {
            CryptoConfig cryptoConfig = config.getEncrCryptoConfig();
            String provider = cryptoConfig.getProvider();
            if (log.isDebugEnabled()) {
                log.debug("Using provider: " + provider);
            }
            Properties prop = cryptoConfig.getProp();
            prop.put(CRYPTO_PROVIDER, provider);

            String cryptoKey = null;
            String interval = null;
            if (cryptoConfig.isCacheEnabled()) {
                if (cryptoConfig.getCryptoKey() != null) {
                    cryptoKey = prop.getProperty(cryptoConfig.getCryptoKey());
                    interval = cryptoConfig.getCacheRefreshInterval();
                }
                else if(provider.equals(RampartConstants.MERLIN_CRYPTO_IMPL)){
                    cryptoKey = cryptoConfig.getProp().getProperty(RampartConstants.MERLIN_CRYPTO_IMPL_CACHE_KEY);
                }
            }


            if (cryptoKey != null) {
                // Crypto caching is enabled
                crypto = retrieveCryptoFromCache(cryptoKey.trim() + "#" + provider.trim(), interval);
            }

            if (crypto == null) {
                // cache miss
                crypto = createCrypto(prop, loader);

                if (cryptoKey != null) {
                    // Crypto caching is enabled - cache the Crypto object
                    cacheCrypto(cryptoKey.trim() + "#" + provider.trim(), crypto);
                }
            }
        } else {
            log.debug("Trying the signature crypto info");
            crypto = getSignatureCrypto(config, loader);
        }
        return crypto;
    }

    private static Crypto createCrypto(Properties properties, ClassLoader classLoader) throws RampartException {

        try {
            return CryptoFactory.getInstance(properties, classLoader);
        } catch (WSSecurityException e) {
            log.error("Error loading crypto properties.", e);
            throw new RampartException("cannotCrateCryptoInstance", e);
        }
    }
    
    /**
     * Create the <code>Crypto</code> instance for signature using information 
     * from the rampart configuration assertion
     * 
     * @param config
     * @return The <code>Crypto</code> instance to be used for signature
     * @throws RampartException
     */
    public static Crypto getSignatureCrypto(RampartConfig config, ClassLoader loader)
            throws RampartException {

        log.debug("Loading Signature crypto");

        Crypto crypto = null;

        if (config != null && config.getSigCryptoConfig() != null) {
            CryptoConfig cryptoConfig = config.getSigCryptoConfig();
            String provider = cryptoConfig.getProvider();
            if (log.isDebugEnabled()) {
                log.debug("Using provider: " + provider);
            }
            Properties prop = cryptoConfig.getProp();
            prop.put(CRYPTO_PROVIDER, provider);
            String cryptoKey = null;
            String interval = null;

            if (cryptoConfig.isCacheEnabled()) {
                if (cryptoConfig.getCryptoKey() != null) {
                    cryptoKey = prop.getProperty(cryptoConfig.getCryptoKey());
                    interval = cryptoConfig.getCacheRefreshInterval();
                }
                else if(provider.equals(RampartConstants.MERLIN_CRYPTO_IMPL)){
                    cryptoKey = cryptoConfig.getProp().getProperty(RampartConstants.MERLIN_CRYPTO_IMPL_CACHE_KEY);
                }
            }

            if (cryptoKey != null) {
                // cache enabled
                crypto = retrieveCryptoFromCache(cryptoKey.trim() + "#" + provider.trim(), interval);
            }

            if (crypto == null) {
                // cache miss
                crypto = createCrypto(prop, loader);
                if (cryptoKey != null) {
                    // cache enabled - let's cache
                    cacheCrypto(cryptoKey.trim() + "#" + provider.trim(), crypto);
                }
            }
        }
        return crypto;
    }
    
    
    /**
     * figureout the key identifier of a give X509Token
     * @param token
     * @return The key identifier of a give X509Token
     * @throws RampartException
     */
    public static int getKeyIdentifier(X509Token token) throws RampartException {
        if (token.isRequireIssuerSerialReference()) {
            return WSConstants.ISSUER_SERIAL;
        } else if (token.isRequireThumbprintReference()) {
            return WSConstants.THUMBPRINT_IDENTIFIER;
        } else if (token.isRequireEmbeddedTokenReference()) {
            return WSConstants.BST_DIRECT_REFERENCE;
        } else {
            throw new RampartException(
                    "unknownKeyRefSpeficier");

        }
    }
    
    /**
     * Process a give issuer address element and return the address.
     * @param issuerAddress
     * @return The address of an issuer address element
     * @throws RampartException If the issuer address element is malformed.
     */
    public static String processIssuerAddress(OMElement issuerAddress) 
        throws RampartException {

    	if(issuerAddress == null){
    		throw new RampartException("invalidIssuerAddress", 
    		                           new String[] { "Issuer address null" });
    	}
    	
    	if(issuerAddress.getText() == null || "".equals(issuerAddress.getText())) {
    		throw new RampartException("invalidIssuerAddress", 
    		                           new String[] { issuerAddress.toString() });
        }

    	return issuerAddress.getText().trim();
    }
    
    /**
     * Retrieve policy using metadata reference 
     * <wsa:Metadata xmlns:wsa="http://www.w3.org/2005/08/addressing">
     *  <mex:Metadata
     *       xmlns:mex="http://schemas.xmlsoap.org/ws/2004/09/mex"
     *       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
     *           <mex:MetadataSection>
     *                  <mex:MetadataReference>
     *                      <wsa:Address>http://address/of/mex/service</wsa:Address>
     *                  </mex:MetadataReference>
     *           </mex:MetadataSection>
     *  </mex:Metadata>
     * </wsa:Metadata>
     * @param mex Metadata element 
     * @return Policy from the mex service
     */
    public static Policy getPolicyFromMetadataRef(OMElement mex) throws RampartException {
        
        try {
            Metadata metadata = new Metadata();
            metadata.fromOM(mex.getFirstElement());
            
            MetadataSection[] metadataSections = metadata.getMetadatSections();
            MetadataReference reference = metadataSections[0].getMetadataReference();
            
            MexClient serviceClient = new MexClient();

            Options options = serviceClient.getOptions();
            options.setTo(reference.getEPR());
            options.setAction(DRConstants.SPEC.Actions.GET_METADATA_REQUEST);
            
            OMElement request = serviceClient.setupGetMetadataRequest(
                                                        MexConstants.SPEC.DIALECT_TYPE_POLICY,null);
            OMElement result = serviceClient.sendReceive(request);
            
            metadata.fromOM(result);
            MetadataSection[] mexSecs =  metadata.getMetadataSection(MexConstants.SPEC.DIALECT_TYPE_POLICY, null);
            OMElement policyElement = (OMElement) mexSecs[0].getInlineData();
            
            return PolicyEngine.getPolicy(policyElement);
            
            
        } catch (MexException e) {
            throw new RampartException("Error Retrieving the policy from mex", e);
        } catch (AxisFault e) {
            throw new RampartException("Error Retrieving the policy from mex", e);
        }
        
    }
    
    public static Policy addRampartConfig (RampartMessageData rmd, Policy policy) {
        
        RampartConfig servicRampConf = rmd.getPolicyData().getRampartConfig();        
        RampartConfig stsRampConf = new RampartConfig();
        
        //TODO copy all the properties of service ramp conf to sts ramp conf
        stsRampConf.setUser(servicRampConf.getUser());
        stsRampConf.setSigCryptoConfig(servicRampConf.getSigCryptoConfig());
        stsRampConf.setPwCbClass(servicRampConf.getPwCbClass());
        
        stsRampConf.setEncryptionUser(servicRampConf.getStsAlias());
        stsRampConf.setEncrCryptoConfig(servicRampConf.getStsCryptoConfig());
        
        policy.addAssertion(stsRampConf);
        
        return policy;
        
    }
    
    
    public static OMElement createRSTTempalteForSCT(int conversationVersion, 
            int wstVersion) throws RampartException {
        try {
            log.debug("Creating RSTTemplate for an SCT request");
            OMFactory fac = OMAbstractFactory.getOMFactory();
            
            OMNamespace wspNs = fac.createOMNamespace(SPConstants.P_NS, "wsp");
            OMElement rstTempl = fac.createOMElement(
                    SPConstants.REQUEST_SECURITY_TOKEN_TEMPLATE,
                    wspNs);
            
            //Create TokenType element and set the value
            OMElement tokenTypeElem = TrustUtil.createTokenTypeElement(
                    wstVersion, rstTempl);
            String tokenType = ConversationConstants
                    .getWSCNs(conversationVersion)
                    + ConversationConstants.TOKEN_TYPE_SECURITY_CONTEXT_TOKEN;
            tokenTypeElem.setText(tokenType);
            
            return rstTempl;
        } catch (TrustException e) {
            throw new RampartException("errorCreatingRSTTemplateForSCT", e);
        } catch (ConversationException e) {
            throw new RampartException("errorCreatingRSTTemplateForSCT", e);
        }
    }
    

    public static int getTimeToLive(RampartMessageData messageData) {

        RampartConfig rampartConfig = messageData.getPolicyData().getRampartConfig();
        if (rampartConfig != null) {
            String ttl = rampartConfig.getTimestampTTL();
            int ttl_i = 0;
            if (ttl != null) {
                try {
                    ttl_i = Integer.parseInt(ttl);
                } catch (NumberFormatException e) {
                    ttl_i = messageData.getTimeToLive();
                }
            }
            if (ttl_i <= 0) {
                ttl_i = messageData.getTimeToLive();
            }
            return ttl_i;
        } else {
            return RampartConfig.DEFAULT_TIMESTAMP_TTL;
        }
    }

    public static int getTimestampMaxSkew(RampartMessageData messageData) {

        RampartConfig rampartConfig = messageData.getPolicyData().getRampartConfig();
        if (rampartConfig != null) {
            String maxSkew = rampartConfig.getTimestampMaxSkew();
            int maxSkew_i = 0;
            if (maxSkew != null) {
                try {
                    maxSkew_i = Integer.parseInt(maxSkew);
                } catch (NumberFormatException e) {
                    maxSkew_i = messageData.getTimestampMaxSkew();
                }
            }
            if (maxSkew_i < 0) {
                maxSkew_i = 0;
            }
            return maxSkew_i;
        } else {
            return RampartConfig.DEFAULT_TIMESTAMP_MAX_SKEW;
        }
    }

    /**
     * Obtain a security context token.
     * @param rmd
     * @param secConvTok
     * @return Return the SecurityContextidentifier of the token
     * @throws TrustException
     * @throws RampartException
     */
    public static String getSecConvToken(RampartMessageData rmd,
            SecureConversationToken secConvTok) throws TrustException,
            RampartException {
        String action = TrustUtil.getActionValue(
                rmd.getWstVersion(),
                RahasConstants.RST_ACTION_SCT);
        
        // Get sts epr
        OMElement issuerEpr = secConvTok.getIssuerEpr();
        String issuerEprAddress = rmd.getMsgContext().getTo().getAddress();
        if(issuerEpr != null) {
            issuerEprAddress = RampartUtil.processIssuerAddress(issuerEpr);
        }
        
        //Find SC version
        int conversationVersion = rmd.getSecConvVersion();
        
        OMElement rstTemplate = RampartUtil.createRSTTempalteForSCT(
                conversationVersion, 
                rmd.getWstVersion());
        
        Policy stsPolicy = null;

        //Try boot strap policy
        Policy bsPol = secConvTok.getBootstrapPolicy();
        
        if(bsPol != null) {
            log.debug("BootstrapPolicy found");
            bsPol.addAssertion(rmd.getPolicyData().getRampartConfig());
            //copy the <wsoma:OptimizedMimeSerialization/> to BootstrapPolicy
            if (rmd.getPolicyData().getMTOMAssertion() != null) {
              bsPol.addAssertion(rmd.getPolicyData().getMTOMAssertion());  
            }
            stsPolicy = bsPol;
        } else {
            //No bootstrap policy use issuer policy
            log.debug("No bootstrap policy, using issuer policy");
            stsPolicy = rmd.getPolicyData().getIssuerPolicy();
        }
        
        String id = getToken(rmd, rstTemplate,
                issuerEprAddress, action, stsPolicy);

        if (log.isDebugEnabled()) {
            log.debug("SecureConversationToken obtained: id=" + id);
        }
        return id;
    }
    

    /**
     * Obtain an issued token.
     * @param rmd
     * @param issuedToken
     * @return The identifier of the issued token
     * @throws RampartException
     */
    public static String getIssuedToken(RampartMessageData rmd,
            IssuedToken issuedToken) throws RampartException {

        try {
            
            //TODO : Provide the overriding mechanism to provide a custom way of 
            //obtaining a token
            
            String action = TrustUtil.getActionValue(rmd.getWstVersion(),
                    RahasConstants.RST_ACTION_ISSUE);

            // Get sts epr
            String issuerEprAddress = RampartUtil.processIssuerAddress(issuedToken
                    .getIssuerEpr());

            OMElement rstTemplate = issuedToken.getRstTemplate();

            // Get STS policy
            Policy stsPolicy = (Policy)rmd.getMsgContext().getProperty(RampartMessageData.RAMPART_STS_POLICY);
            
            if( stsPolicy == null && issuedToken.getIssuerMex() != null) {
                stsPolicy = RampartUtil.getPolicyFromMetadataRef(issuedToken.getIssuerMex());
                RampartUtil.addRampartConfig(rmd, stsPolicy);
            }

            String id = getToken(rmd, rstTemplate, issuerEprAddress, action,
                    stsPolicy);

            if (log.isDebugEnabled()) {
                log.debug("Issued token obtained: id=" + id);
            }
            return id;
        } catch (TrustException e) {
            throw new RampartException("errorInObtainingToken", e);
        } 
    }
    
    /**
     * Request a token.
     * @param rmd
     * @param rstTemplate
     * @param issuerEpr
     * @param action
     * @param issuerPolicy
     * @return Return the identifier of the obtained token
     * @throws RampartException
     */
    public static String getToken(RampartMessageData rmd, OMElement rstTemplate,
            String issuerEpr, String action, Policy issuerPolicy) throws RampartException {

        try {
            //First check whether the user has provided the token
            MessageContext msgContext = rmd.getMsgContext();
            String customTokeId = (String) msgContext
                    .getProperty(RampartMessageData.KEY_CUSTOM_ISSUED_TOKEN);
            if(customTokeId != null) {
                return customTokeId;
            } else {
    
                Axis2Util.useDOOM(false);
                
                STSClient client = new STSClient(rmd.getMsgContext()
                        .getConfigurationContext());
                // Set request action
                client.setAction(action);
                
                client.setVersion(rmd.getWstVersion());
                
                client.setRstTemplate(rstTemplate);
        
                // Set crypto information
                Crypto crypto = RampartUtil.getSignatureCrypto(rmd.getPolicyData().getRampartConfig(), 
                        rmd.getMsgContext().getAxisService().getClassLoader());
                CallbackHandler cbh = RampartUtil.getPasswordCB(rmd);
                client.setCryptoInfo(crypto, cbh);
        
                // Get service policy
                Policy servicePolicy = rmd.getServicePolicy();
        
                // Get service epr
                String servceEprAddress = rmd.getMsgContext()
                        .getOptions().getTo().getAddress();
        
                //If addressing version can be found set it
                Object addrVersionNs = msgContext.getProperty(AddressingConstants.WS_ADDRESSING_VERSION);
                if(addrVersionNs != null) {
                    client.setAddressingNs((String)addrVersionNs);
                }
                
                Options options = new Options();
                
                options.setUserName(rmd.getMsgContext().getOptions().getUserName());
                options.setPassword(rmd.getMsgContext().getOptions().getPassword());
                
                if (msgContext.getProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER) != null) {
                    Protocol protocolHandler =
                        (Protocol)msgContext.getProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER);;
                    options.setProperty(HTTPConstants.CUSTOM_PROTOCOL_HANDLER, protocolHandler);                 
                } 
                
                if (msgContext.getParameter(WSHandlerConstants.PW_CALLBACK_REF) != null ) {
                    Parameter pwCallback = msgContext.getParameter(WSHandlerConstants.PW_CALLBACK_REF);
                    client.addParameter(pwCallback);
                }
                
                client.setOptions(options);
                
                //Set soap version
                if (msgContext.isSOAP11()) {
                    client.setSoapVersion(SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI);
                } else {
                    client.setSoapVersion(SOAP12Constants.SOAP_ENVELOPE_NAMESPACE_URI);
                }
                
                
                //Make the request
                org.apache.rahas.Token rst = 
                    client.requestSecurityToken(servicePolicy, 
                                                issuerEpr,
                                                issuerPolicy, 
                                                servceEprAddress);
                
                //Add the token to token storage
                rst.setState(Token.ISSUED);
                rmd.getTokenStorage().add(rst);
                Axis2Util.useDOOM(true);
                return rst.getId();
            }
        } catch (Exception e) {
            throw new RampartException("errorInObtainingToken", e);
        }
    }

    public static String getSoapBodyId(SOAPEnvelope env) {
        return addWsuIdToElement(env.getBody());
    }
    
    public static String addWsuIdToElement(OMElement elem) {
        String id;
        
        //first try to get the Id attr
        OMAttribute idAttr = elem.getAttribute(new QName("Id"));
        if(idAttr == null) {
            //then try the wsu:Id value
            idAttr = elem.getAttribute(new QName(WSConstants.WSU_NS, "Id"));
        }
        
        if(idAttr != null) {
            id = idAttr.getAttributeValue();
        } else {
            //Add an id
            OMNamespace ns = elem.getOMFactory().createOMNamespace(
                    WSConstants.WSU_NS, WSConstants.WSU_PREFIX);
            id = "Id-" + elem.hashCode();
            idAttr = elem.getOMFactory().createOMAttribute("Id", ns, id);
            elem.addAttribute(idAttr);
        }
        
        return id;
    }
    
    /**
     * Change the owner document of the given node. The method first attempts to move the node using
     * {@link Document#adoptNode(Node)}. If that fails, it will import the node into the target
     * document using {@link Document#importNode(Node, boolean)}.
     * 
     * @param targetDocument
     *            the target document
     * @param node
     *            the node to adopt or import
     * @return the adopted or imported node
     */
    public static Node adoptNode(Document targetDocument, Node node) {
        Node result = targetDocument.adoptNode(node);
        if (result == null) {
            result = targetDocument.importNode(node, true);
        }
        return result;
    }
    
    public static Element appendChildToSecHeader(RampartMessageData rmd,
            OMElement elem) {
        return appendChildToSecHeader(rmd, (Element)elem);
    }
    
    public static Element appendChildToSecHeader(RampartMessageData rmd,
            Element elem) {
        Element secHeaderElem = rmd.getSecHeader().getSecurityHeader();
        Node node = adoptNode(secHeaderElem.getOwnerDocument(), elem);
        return (Element)secHeaderElem.appendChild(node);
    }

    public static Element insertSiblingAfter(RampartMessageData rmd,
            Element child, Element sibling) {
        if (child == null) {
            return appendChildToSecHeader(rmd, sibling);
        } else {
            if (child.getOwnerDocument().equals(sibling.getOwnerDocument())) {

                if (child.getParentNode() == null
                        && !child.getLocalName().equals("UsernameToken")) {
                    rmd.getSecHeader().getSecurityHeader().appendChild(child);
                }
                ((OMElement) child).insertSiblingAfter((OMElement) sibling);
                return sibling;
            } else {
                Element newSib = (Element) child.getOwnerDocument().importNode(
                        sibling, true);
                ((OMElement) child).insertSiblingAfter((OMElement) newSib);
                return newSib;
            }
        }
    }
    
    public static Element insertSiblingBefore(RampartMessageData rmd, Element child, Element sibling) {
        if(child == null) {
            return appendChildToSecHeader(rmd, sibling);
        } else {
            if(child.getOwnerDocument().equals(sibling.getOwnerDocument())) {
                ((OMElement)child).insertSiblingBefore((OMElement)sibling);
                return sibling;
            } else {
                Element newSib = (Element)child.getOwnerDocument().importNode(sibling, true);
                ((OMElement)child).insertSiblingBefore((OMElement)newSib);
                return newSib;
            }
        }
        
    }
    
    public static List<WSEncryptionPart> getEncryptedParts(RampartMessageData rmd) {
		RampartPolicyData rpd = rmd.getPolicyData();
		SOAPEnvelope envelope = rmd.getMsgContext().getEnvelope();
		List<WSEncryptionPart> encryptedPartsElements = getPartsAndElements(false, envelope,
				rpd.isEncryptBody() && !rpd.isEncryptBodyOptional(), rpd
						.getEncryptedParts(), rpd.getEncryptedElements(), rpd
						.getDeclaredNamespaces());
		return getContentEncryptedElements(encryptedPartsElements, envelope,
				rpd.getContentEncryptedElements(), rpd.getDeclaredNamespaces());
	}

	public static List<WSEncryptionPart> getSignedParts(RampartMessageData rmd) {
		RampartPolicyData rpd = rmd.getPolicyData();
		SOAPEnvelope envelope = rmd.getMsgContext().getEnvelope();

        //"signAllHeaders" indicates that all the headers should be signed.
        if (rpd.isSignAllHeaders()) {
            Iterator childHeaders = envelope.getHeader().getChildElements();
            while (childHeaders.hasNext()) {
               OMElement hb = (OMElement) childHeaders.next();
                if (!(hb.getLocalName().equals(WSConstants.WSSE_LN)
                        && hb.getNamespace().getNamespaceURI().equals(WSConstants.WSSE_NS))) {
                    rpd.addSignedPart(hb.getNamespace().getNamespaceURI(),hb.getLocalName());
                }
           }
        }

		return getPartsAndElements(true, envelope, rpd.isSignBody()
				&& !rpd.isSignBodyOptional(), rpd.getSignedParts(), rpd
				.getSignedElements(), rpd.getDeclaredNamespaces());
	}

	public static List<WSEncryptionPart> getSupportingEncryptedParts(RampartMessageData rmd,
			SupportingPolicyData rpd) {
		SOAPEnvelope envelope = rmd.getMsgContext().getEnvelope();
		return getPartsAndElements(false, envelope, rpd.isEncryptBody()
				&& !rpd.isEncryptBodyOptional(), rpd.getEncryptedParts(), rpd
				.getEncryptedElements(), rpd.getDeclaredNamespaces());
	}

	public static List<WSEncryptionPart> getSupportingSignedParts(RampartMessageData rmd,
			SupportingPolicyData rpd) {
		SOAPEnvelope envelope = rmd.getMsgContext().getEnvelope();
		return getPartsAndElements(true, envelope, rpd.isSignBody()
				&& !rpd.isSignBodyOptional(), rpd.getSignedParts(), rpd
				.getSignedElements(), rpd.getDeclaredNamespaces());
	}
    
    public static Set findAllPrefixNamespaces(OMElement currentElement, HashMap decNamespacess)
    {
    	Set<OMNamespace> results = new HashSet<OMNamespace>();
    	
    	//Find declared namespaces
    	findPrefixNamespaces(currentElement,results);
    	
    	//Get all default namespaces
    	List defaultNamespaces = getDefaultPrefixNamespaces(currentElement.getOMFactory());
        for (Object defaultNamespace : defaultNamespaces) {
            OMNamespace ns = (OMNamespace) defaultNamespace;
            results.add(ns);
        }

        for (Object o : decNamespacess.keySet()) {
            String prefix = (String) o;
            String ns = (String) decNamespacess.get(prefix);
            OMFactory omFactory = currentElement.getOMFactory();
            OMNamespace namespace = omFactory.createOMNamespace(ns, prefix);
            results.add(namespace);

        }
    	
    	return results;
    }

    private static void findPrefixNamespaces(OMElement e, Set<OMNamespace> results) {

        Iterator iterator = e.getAllDeclaredNamespaces();

        if (iterator != null) {
            while (iterator.hasNext())
                results.add((OMNamespace)iterator.next());
        }

        Iterator children = e.getChildElements();

        while (children.hasNext()) {
            findPrefixNamespaces((OMElement) children.next(), results);
        }
    }
    
    private static List getDefaultPrefixNamespaces(OMFactory factory)
    {
    	List<OMNamespace> namespaces = new ArrayList<OMNamespace>();

    	// put default namespaces here (sp, soapenv, wsu, etc...)
    	namespaces.add(factory.createOMNamespace(WSConstants.ENC_NS, WSConstants.ENC_PREFIX));
    	namespaces.add(factory.createOMNamespace(WSConstants.SIG_NS, WSConstants.SIG_PREFIX));
    	namespaces.add(factory.createOMNamespace(WSConstants.WSSE_NS, WSConstants.WSSE_PREFIX));
    	namespaces.add(factory.createOMNamespace(WSConstants.WSU_NS, WSConstants.WSU_PREFIX));
    	
    	return namespaces;
    	
    }
    
    public static List<WSEncryptionPart> getContentEncryptedElements (List<WSEncryptionPart> encryptedPartsElements,
                                                 SOAPEnvelope envelope,List<String> elements, HashMap decNamespaces ) {
        
        Set namespaces = findAllPrefixNamespaces(envelope, decNamespaces);

        for (String expression : elements) {
            try {
                XPath xp = new AXIOMXPath(expression);

                for (Object objectNamespace : namespaces) {
                    OMNamespace tmpNs = (OMNamespace) objectNamespace;
                    xp.addNamespace(tmpNs.getPrefix(), tmpNs.getNamespaceURI());
                }

                List selectedNodes = xp.selectNodes(envelope);

                for (Object selectedNode : selectedNodes) {
                    OMElement e = (OMElement) selectedNode;

                    String localName = e.getLocalName();
                    String namespace = e.getNamespace() != null ? e.getNamespace().getNamespaceURI() : null;

                    OMAttribute wsuIdAttribute = e.getAttribute(new QName(WSConstants.WSU_NS, "Id"));

                    String wsuId = null;
                    if (wsuIdAttribute != null) {
                        wsuId = wsuIdAttribute.getAttributeValue();
                    }

                    encryptedPartsElements.add(createEncryptionPart(localName,
                            wsuId, namespace, "Content", expression));

                }

            } catch (JaxenException e) {
                // This has to be changed to propagate an instance of a RampartException up
                throw new RuntimeException(e);
            }
        }
        
     
        return encryptedPartsElements;
        
    }


    /**
     * Creates an Encryption or Signature paert with given name and id. Name must not be null.
     * @param name The name of the part
     * @param id The id of the part.
     * @return WSEncryptionPart.
     */
    public static WSEncryptionPart createEncryptionPart (String name, String id) {

        return createEncryptionPart(name, id, null, null, null);
    }

    /**
     * Creates an encryption part. Could be a part or could be an element pointed through xpath expression.
     * @param name Name of the element.
     * @param id The id of the element
     * @param namespace Namespace of the element.
     * @param modifier Modifier "Content" or "Element"
     * @return A WSEncryptionPart
     */
    public static WSEncryptionPart createEncryptionPart(String name, String id,
                                                         String namespace, String modifier) {

        return createEncryptionPart(name, id, namespace, modifier, null);
    }

     /**
     * Creates an encryption part. Could be a part or could be an element pointed through xpath expression.
     * @param name Name of the element.
     * @param id The id of the element
     * @param namespace Namespace of the element.
     * @param modifier Modifier "Content" or "Element"
     * @param xPath The xPath expression
      * @return A WSEncryptionPart
     */
    public static WSEncryptionPart createEncryptionPart(String name, String id,
                                                         String namespace, String modifier,String xPath) {

        // The part name must not be null !!
        assert name != null;

        WSEncryptionPart wsEncryptionPart = new WSEncryptionPart(name, namespace, modifier);
        wsEncryptionPart.setId(id);
        wsEncryptionPart.setXpath(xPath);

        return wsEncryptionPart;
    }
    
    public static List<WSEncryptionPart> getPartsAndElements(boolean sign, SOAPEnvelope envelope, boolean includeBody,
                                                             List<WSEncryptionPart> parts, List<String> elements,
                                                             HashMap decNamespaces) {

        List<OMElement> found = new ArrayList<OMElement>();
        List<WSEncryptionPart> result = new ArrayList<WSEncryptionPart>();

        // check body
        if(includeBody) {

            String wsuId = addWsuIdToElement(envelope.getBody());

            if( sign ) {
                result.add(createEncryptionPart(envelope.getBody().getLocalName(), wsuId,
                        null, null));
            } else {
                result.add(createEncryptionPart(envelope.getBody().getLocalName(), wsuId, null, "Content"));
            }

            // TODO can we remove this ?
            found.add( envelope.getBody() );
        }
        
        // Search envelope header for 'parts' from Policy (SignedParts/EncryptedParts)

        SOAPHeader header = envelope.getHeader();

        for (WSEncryptionPart part : parts) {
            if (part.getName() == null) {
                // NO name - search by namespace
                ArrayList headerList = header.getHeaderBlocksWithNSURI(part.getNamespace());

                for (Object aHeaderList : headerList) {
                    SOAPHeaderBlock shb = (SOAPHeaderBlock) aHeaderList;

                    // find reference in envelope
                    OMElement e = header.getFirstChildWithName(shb.getQName());

                    if (!found.contains(e)) {
                        // found new
                        found.add(e);

                        if (sign) {
                            result.add(createEncryptionPart(e.getLocalName(), null,
                                    part.getNamespace(), "Content"));
                        } else {

                            OMAttribute wsuIdAttribute = e.getAttribute(new QName(WSConstants.WSU_NS, "Id"));

                            String wsuId = null;
                            if (wsuIdAttribute != null) {
                                wsuId = wsuIdAttribute.getAttributeValue();
                            }

                            result.add(createEncryptionPart(e.getLocalName(),wsuId,
                                    part.getNamespace(), "Element"));
                        }
                    }
                }
            } else {
                // try to find
                OMElement e = header.getFirstChildWithName(new QName(part.getNamespace(), part.getName()));
                if (e != null) {
                    if (!found.contains(e)) {
                        // found new (reuse wsep)
                        found.add(e);
                        OMAttribute wsuId = e.getAttribute(new QName(WSConstants.WSU_NS, "Id"));

                        if (wsuId != null) {
                            part.setEncId(wsuId.getAttributeValue());
                        }

                        result.add(part);
                    }
                }
            }
        }
        
        // ?? Search for 'Elements' here
        
        // decide what exactly is going to be used - only the default namespaces, or the list of all declared namespaces in the message !
        Set namespaces = findAllPrefixNamespaces(envelope, decNamespaces);

        for (String expression : elements) {
            try {
                XPath xp = new AXIOMXPath(expression);

                for (Object objectNamespace : namespaces) {
                    OMNamespace tmpNs = (OMNamespace) objectNamespace;
                    xp.addNamespace(tmpNs.getPrefix(), tmpNs.getNamespaceURI());
                }

                List selectedNodes = xp.selectNodes(envelope);

                for (Object selectedNode : selectedNodes) {
                    OMElement e = (OMElement) selectedNode;
                    String localName = e.getLocalName();
                    String namespace = e.getNamespace() != null ? e.getNamespace().getNamespaceURI() : null;

                    if (sign) {

                        result.add(createEncryptionPart(localName, null, namespace, "Content", expression));

                    } else {

                        OMAttribute wsuIdAttribute = e.getAttribute(new QName(WSConstants.WSU_NS, "Id"));

                        String wsuId = null;
                        if (wsuIdAttribute != null) {
                            wsuId = wsuIdAttribute.getAttributeValue();
                        }

                        result.add(createEncryptionPart(localName, wsuId, namespace, "Element", expression));
                    }
                }

            } catch (JaxenException e) {
                // This has to be changed to propagate an instance of a RampartException up
                throw new RuntimeException(e);
            }
        }

        return result;
    }
    
    /**
     * Get a element for SOAP 
     * @param envelope   SOAP Envelope of which we should check required elements
     * @param decNamespaces  Declared namespaces in RequiredElements assertion
     * @param expression  XPATH expression of required elements
     * @return
     */
    public static boolean checkRequiredElements(SOAPEnvelope envelope, HashMap decNamespaces, String expression) {

        // The XPath expression must be evaluated against the SOAP header
        // http://docs.oasis-open.org/ws-sx/ws-securitypolicy/200702/ws-securitypolicy-1.2-spec-os.html#_Toc161826519
        SOAPHeader header = envelope.getHeader();
        Set namespaces = findAllPrefixNamespaces(header, decNamespaces);

        try {
            XPath xp = new AXIOMXPath(expression);

            for (Object namespace : namespaces) {
                OMNamespace tmpNs = (OMNamespace) namespace;
                xp.addNamespace(tmpNs.getPrefix(), tmpNs.getNamespaceURI());
            }

            List selectedNodes = xp.selectNodes(header);

            if (selectedNodes.size() == 0) {
                return false;
            }

        } catch (JaxenException e) {
            // This has to be changed to propagate an instance of a RampartException up
            throw new RuntimeException(e);
        }

        return true;
    }
    
    
    public static KeyGenerator getEncryptionKeyGenerator(String symEncrAlgo) throws WSSecurityException {
        KeyGenerator keyGen;
        try {
            /*
             * Assume AES as default, so initialize it
             */
            keyGen = KeyGenerator.getInstance("AES");
            if (symEncrAlgo.equalsIgnoreCase(WSConstants.TRIPLE_DES)) {
                keyGen = KeyGenerator.getInstance("DESede");
            } else if (symEncrAlgo.equalsIgnoreCase(WSConstants.AES_128)) {
                keyGen.init(128);
            } else if (symEncrAlgo.equalsIgnoreCase(WSConstants.AES_192)) {
                keyGen.init(192);
            } else if (symEncrAlgo.equalsIgnoreCase(WSConstants.AES_256)) {
                keyGen.init(256);
            } else {
                return null;
            }
        } catch (NoSuchAlgorithmException e) {
            throw new WSSecurityException(
                    WSSecurityException.UNSUPPORTED_ALGORITHM, null, null, e);
        }
        return keyGen;
    }
    
    /**
     * Creates the unique (reproducible) id for to hold the context identifier
     * of the message exchange.
     * @return Id to hold the context identifier in the message context
     */
    public static String getContextIdentifierKey(MessageContext msgContext) {
        return msgContext.getAxisService().getName();
    }
    
    
    /**
     * Returns the map of security context token identifiers
     * @return the map of security context token identifiers
     */
    public static Hashtable getContextMap(MessageContext msgContext) {
        //Fist check whether its there
        Object map = msgContext.getConfigurationContext().getProperty(
                ConversationConstants.KEY_CONTEXT_MAP);
        
        if(map == null) {
            //If not create a new one
            map = new Hashtable();
            //Set the map globally
            msgContext.getConfigurationContext().setProperty(
                    ConversationConstants.KEY_CONTEXT_MAP, map);
        }
        
        return (Hashtable)map;
    }
    
    public static boolean isTokenValid(RampartMessageData rmd, String id) throws RampartException {
        try {
            org.apache.rahas.Token token = rmd.getTokenStorage().getToken(id);
            return token!= null && token.getState() == org.apache.rahas.Token.ISSUED;
        } catch (TrustException e) {
            throw new RampartException("errorExtractingToken");
        } 
    }
    
    public static void setEncryptionUser(RampartMessageData rmd, WSSecEncryptedKey encrKeyBuilder)
            throws RampartException {
        RampartPolicyData rpd = rmd.getPolicyData();
        String encrUser = rpd.getRampartConfig().getEncryptionUser();
        setEncryptionUser(rmd, encrKeyBuilder, encrUser);
    }
    
    public static void setEncryptionUser(RampartMessageData rmd, WSSecEncryptedKey encrKeyBuilder,
            String encrUser) throws RampartException {
        RampartPolicyData rpd = rmd.getPolicyData();
        
        if (encrUser == null) {
            encrUser = rpd.getRampartConfig().getEncryptionUser();
        }
        
        if (encrUser == null || "".equals(encrUser)) {
            throw new RampartException("missingEncryptionUser");
        }
        if(encrUser.equals(WSHandlerConstants.USE_REQ_SIG_CERT)) {
            List<WSHandlerResult> resultsObj
                    = (List<WSHandlerResult>)rmd.getMsgContext().getProperty(WSHandlerConstants.RECV_RESULTS);
            if(resultsObj != null) {
                encrKeyBuilder.setUseThisCert(getReqSigCert(resultsObj));
                 
                //TODO This is a hack, this should not come under USE_REQ_SIG_CERT
                if(encrKeyBuilder.isCertSet()) {
                	encrKeyBuilder.setUserInfo(getUsername(resultsObj));
                }
                	
                
            } else {
                throw new RampartException("noSecurityResults");
            }
        } else {
            encrKeyBuilder.setUserInfo(encrUser);
        }
    }
    
    /**
     * Sets the keyIdentifierType of <code>WSSecSignature</code> or <code>WSSecEncryptedKey</code> 
     * according to the given <code>Token</code> and <code>RampartPolicyData</code>
     * First check the requirements specified under Token Assertion and if not found check 
     * the WSS11 and WSS10 assertions
     */
    
    public static void setKeyIdentifierType(RampartMessageData rmd, WSSecBase secBase,org.apache.ws.secpolicy.model.Token token) {

        // Use a reference rather than the binary security token if: the policy never allows the token to be
        // included; or this is the recipient and the token should only be included in requests; or this is
        // the initiator and the token should only be included in responses.
        final boolean useReference = token.getInclusion() == SPConstants.INCLUDE_TOKEN_NEVER
                                     || !rmd.isInitiator() && token.getInclusion() == SPConstants.INCLUDE_TOEKN_ALWAYS_TO_RECIPIENT
                                     || rmd.isInitiator() && token.getInclusion() == SPConstants.INCLUDE_TOEKN_ALWAYS_TO_INITIATOR;
        if (useReference) {

    		boolean tokenTypeSet = false;
    		
    		if(token instanceof X509Token) {
    			X509Token x509Token = (X509Token)token;
    			
    			if(x509Token.isRequireIssuerSerialReference()) {
    				secBase.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
    				tokenTypeSet = true;
    			} else if (x509Token.isRequireKeyIdentifierReference()) {
    				secBase.setKeyIdentifierType(WSConstants.SKI_KEY_IDENTIFIER);
    				tokenTypeSet = true;
    			} else if (x509Token.isRequireThumbprintReference()) {
    				secBase.setKeyIdentifierType(WSConstants.THUMBPRINT_IDENTIFIER);
    				tokenTypeSet = true;
    			}
    		} 
    		
    		if (!tokenTypeSet) {
                final RampartPolicyData rpd = rmd.getPolicyData();
	    		Wss10 wss = rpd.getWss11();
				if (wss == null) {
					wss = rpd.getWss10();
				}
				
				if (wss.isMustSupportRefKeyIdentifier()) {
					secBase.setKeyIdentifierType(WSConstants.SKI_KEY_IDENTIFIER);
				} else if (wss.isMustSupportRefIssuerSerial()) {
					secBase.setKeyIdentifierType(WSConstants.ISSUER_SERIAL);
				} else if (wss instanceof Wss11
						&& ((Wss11) wss).isMustSupportRefThumbprint()) {
					secBase.setKeyIdentifierType(WSConstants.THUMBPRINT_IDENTIFIER);
				}
    		}
    		
		} else {
			secBase.setKeyIdentifierType(WSConstants.BST_DIRECT_REFERENCE);
		}
    }
    
    private static X509Certificate getReqSigCert(List<WSHandlerResult> results) {
        /*
        * Scan the results for a matching actor. Use results only if the
        * receiving Actor and the sending Actor match.
        */
        for (WSHandlerResult result : results) {

            List<WSSecurityEngineResult> wsSecEngineResults = result.getResults();
            /*
            * Scan the results for the first Signature action. Use the
            * certificate of this Signature to set the certificate for the
            * encryption action :-).
            */
            for (WSSecurityEngineResult wsSecEngineResult : wsSecEngineResults) {
                Integer actInt = (Integer) wsSecEngineResult.get(WSSecurityEngineResult.TAG_ACTION);
                if (actInt == WSConstants.SIGN) {
                    return (X509Certificate) wsSecEngineResult.get(WSSecurityEngineResult.TAG_X509_CERTIFICATE);
                }
            }
        }
        
        return null;
    }
    
    /**
     * Scan through <code>WSHandlerResult<code> list for a Username token and return
     * the username if a Username Token found 
     * @param results
     * @return
     */
    
    public static String getUsername(List<WSHandlerResult> results) {
        /*
         * Scan the results for a matching actor. Use results only if the
         * receiving Actor and the sending Actor match.
         */
        for (WSHandlerResult result : results) {

            List<WSSecurityEngineResult> wsSecEngineResults = result.getResults();
            /*
            * Scan the results for a username token. Use the username
            * of this token to set the alias for the encryption user
            */
            for (WSSecurityEngineResult wsSecEngineResult : wsSecEngineResults) {
                Integer actInt = (Integer) wsSecEngineResult.get(WSSecurityEngineResult.TAG_ACTION);
                if (actInt == WSConstants.UT) {
                    WSUsernameTokenPrincipal principal = (WSUsernameTokenPrincipal) wsSecEngineResult.
                            get(WSSecurityEngineResult.TAG_PRINCIPAL);
                    return principal.getName();
                }
            }
        }
         
         return null;
    }

    public static String getRequestEncryptedKeyId(List<WSHandlerResult> results) {

        for (WSHandlerResult result : results) {

            List<WSSecurityEngineResult> wsSecEngineResults = result.getResults();
            /*
            * Scan the results for the first Signature action. Use the
            * certificate of this Signature to set the certificate for the
            * encryption action :-).
            */
            for (WSSecurityEngineResult wsSecEngineResult : wsSecEngineResults) {
                Integer actInt = (Integer) wsSecEngineResult.get(WSSecurityEngineResult.TAG_ACTION);
                String encrKeyId = (String) wsSecEngineResult.get(WSSecurityEngineResult.TAG_ID);
                if (actInt == WSConstants.ENCR &&
                        encrKeyId != null) {
                    return encrKeyId;
                }
            }
        }

        return null;
    }
    
    public static byte[] getRequestEncryptedKeyValue(List<WSHandlerResult> results) {

        for (WSHandlerResult result : results) {

            List<WSSecurityEngineResult> wsSecEngineResults = result.getResults();
            /*
            * Scan the results for the first Signature action. Use the
            * certificate of this Signature to set the certificate for the
            * encryption action :-).
            */
            for (WSSecurityEngineResult wsSecEngineResult : wsSecEngineResults) {
                Integer actInt = (Integer) wsSecEngineResult.get(WSSecurityEngineResult.TAG_ACTION);
                byte[] decryptedKey = (byte[]) wsSecEngineResult.get(WSSecurityEngineResult.TAG_SECRET);
                if (actInt == WSConstants.ENCR &&
                        decryptedKey != null) {
                    return decryptedKey;
                }
            }
        }
        
        return null;
    }
    
    /**
     * If the child is present insert the element as a sibling after him.
     * 
     * If the child is null, then prepend the element.
     * 
     * @param rmd
     * @param child
     * @param elem - element mentioned above
     * @return
     */
    public static Element insertSiblingAfterOrPrepend(RampartMessageData rmd, Element child, Element elem) {
        Element retElem = null;
        if (child != null) { // child is not null so insert sibling after
            retElem = RampartUtil.insertSiblingAfter(rmd, child, elem);
        } else { //Prepend
            retElem = prependSecHeader(rmd, elem);
        }

        return retElem;
    }

    public static Element insertSiblingBeforeOrPrepend(RampartMessageData rmd, Element child, Element elem) {
        Element retElem = null;
        if (child != null && child.getPreviousSibling() != null) {
            retElem = RampartUtil.insertSiblingBefore(rmd, child, elem);
        } else { //Prepend
            retElem = prependSecHeader(rmd, elem);
        }

        return retElem;
    }

    private static Element prependSecHeader(RampartMessageData rmd, Element elem) {
        Element retElem = null;

        Element secHeaderElem = rmd.getSecHeader().getSecurityHeader();
        Node node = secHeaderElem.getOwnerDocument().importNode(
                elem, true);
        Element firstElem = (Element) secHeaderElem.getFirstChild();

        if (firstElem == null) {
            retElem = (Element) secHeaderElem.appendChild(node);
        } else {
            if (firstElem.getOwnerDocument().equals(elem.getOwnerDocument())) {
                ((OMElement) firstElem).insertSiblingBefore((OMElement) elem);
                retElem = elem;
            } else {
                Element newSib = (Element) firstElem.getOwnerDocument().importNode(elem, true);
                ((OMElement) firstElem).insertSiblingBefore((OMElement) newSib);
                retElem = newSib;
            }
        }

        return retElem;
    }
    
    /**
     * Method to check whether security header is required in incoming message
     * @param rpd 
     * @return true if a security header is required in the incoming message
     */
    public static boolean isSecHeaderRequired(RampartPolicyData rpd, boolean initiator, 
                                                                                boolean inflow ) {
        
        // Checking for time stamp
        if ( rpd.isIncludeTimestamp() ) {
            return true;
        } 
        
        // Checking for signed parts and elements
        if (rpd.isSignBody() || rpd.getSignedParts().size() != 0 || 
                                    rpd.getSignedElements().size() != 0) {
            return true;
        }
        
        // Checking for encrypted parts and elements
        if (rpd.isEncryptBody() || rpd.getEncryptedParts().size() != 0 || 
                                    rpd.getEncryptedElements().size() != 0 ) {
            return true;
        }   
        
        // Checking for supporting tokens
        SupportingToken supportingTokens;
        
        if (!initiator && inflow || initiator && !inflow ) {
        
            List<SupportingToken> supportingToks = rpd.getSupportingTokensList();
            for (SupportingToken supportingTok : supportingToks) {
                if (supportingTok != null && supportingTok.getTokens().size() != 0) {
                    return true;
                }
            }
            
            supportingTokens = rpd.getSignedSupportingTokens();
            if (supportingTokens != null && supportingTokens.getTokens().size() != 0) {
                return true;
            }
            
            supportingTokens = rpd.getEndorsingSupportingTokens();
            if (supportingTokens != null && supportingTokens.getTokens().size() != 0) {
                return true;
            }
            
            supportingTokens = rpd.getSignedEndorsingSupportingTokens();
            if (supportingTokens != null && supportingTokens.getTokens().size() != 0) {
                return true;
            }
       
            supportingTokens = rpd.getEncryptedSupportingTokens();
            if (supportingTokens != null && supportingTokens.getTokens().size() != 0) {
                return true;
            }
            
            supportingTokens = rpd.getSignedEncryptedSupportingTokens();
            if (supportingTokens != null && supportingTokens.getTokens().size() != 0) {
                return true;
            }
            
            supportingTokens = rpd.getEndorsingEncryptedSupportingTokens();
            if (supportingTokens != null && supportingTokens.getTokens().size() != 0) {
                return true;
            }
            
            supportingTokens = rpd.getSignedEndorsingEncryptedSupportingTokens();
            if (supportingTokens != null && supportingTokens.getTokens().size() != 0) {
                return true;
            }
        }
        
        return false;
        
    }

    public static void handleEncryptedSignedHeaders(List<WSEncryptionPart> encryptedParts,
                                                    List<WSEncryptionPart> signedParts, Document doc) {

        //TODO Is there a more efficient  way to do this ? better search algorithm 
        for (WSEncryptionPart signedPart : signedParts) {
            //This signed part is not a header
            if (signedPart.getNamespace() == null || signedPart.getName() == null) {
                continue;
            }

            for (WSEncryptionPart encryptedPart : encryptedParts) {

                if (encryptedPart.getNamespace() == null || encryptedPart.getName() == null) {
                    continue;
                }

                if (signedPart.getName().equals(encryptedPart.getName()) &&
                        signedPart.getNamespace().equals(encryptedPart.getNamespace())) {

                    String encDataID = encryptedPart.getEncId();

                    // TODO Do we need to go through the whole tree to find element by id ? Verify
                    Element encDataElem = WSSecurityUtil.findElementById(doc.getDocumentElement(), encDataID, false);

                    if (encDataElem != null) {
                        Element encHeader = (Element) encDataElem.getParentNode();
                        String encHeaderId = encHeader.getAttributeNS(WSConstants.WSU_NS, "Id");

                        //For some reason the id might not be available
                        // so the part/element with empty/null id won't be recognized afterwards. 
                        if (encHeaderId != null && !"".equals(encHeaderId.trim())) {
                            signedParts.remove(signedPart);

                            signedParts.add(createEncryptionPart(signedPart.getName(), encHeaderId,
                                    signedPart.getNamespace(),
                                    signedPart.getEncModifier(), signedPart.getXpath()));
                        }

                    }
                }
            }


        }

    }
    
    public static String getSigElementId(RampartMessageData rmd) {
        
        SOAPEnvelope envelope = rmd.getMsgContext().getEnvelope();
        
        SOAPHeader header = envelope.getHeader();
        
        if (header == null ) {
            return null;
        }
        
        ArrayList secHeaders = header.getHeaderBlocksWithNSURI(WSConstants.WSSE_NS);
        
        if (secHeaders != null && secHeaders.size() > 0) {
            QName sigQName = new QName(Constants.SignatureSpecNS,Constants._TAG_SIGNATURE);
            QName wsuIdQName = new QName(WSConstants.WSU_NS,"Id");
            OMElement sigElem = ((SOAPHeaderBlock)secHeaders.get(0)).getFirstChildWithName(sigQName);
            OMAttribute wsuId = sigElem.getAttribute(wsuIdQName);
            
            if (wsuId != null) {
                return wsuId.getAttributeValue();
            }
            
            wsuId = sigElem.getAttribute(new QName("Id"));
            
            if (wsuId != null) {
                return wsuId.getAttributeValue();
            }
            
            
        }
        
        return null;
    }
    
    /**
     * We use this method to prevent the singleton behavior of WSSConfig
     * @return WSSConfig object with the latest settings.    
     */
    
    public static WSSConfig getWSSConfigInstance() {
        
        WSSConfig defaultWssConfig = WSSConfig.getNewInstance();
        WSSConfig wssConfig = WSSConfig.getNewInstance();
        
        wssConfig.setEnableSignatureConfirmation(defaultWssConfig.isEnableSignatureConfirmation());
        wssConfig.setTimeStampStrict(defaultWssConfig.isTimeStampStrict());
        wssConfig.setWsiBSPCompliant(defaultWssConfig.isWsiBSPCompliant());
        wssConfig.setPrecisionInMilliSeconds(defaultWssConfig.isPrecisionInMilliSeconds());
        
        return  wssConfig;
       
    }

    public static void validateTransport(RampartMessageData rmd) throws RampartException {

        RampartPolicyData rpd = rmd.getPolicyData();

        if (rpd == null) {
            return;
        }

        if (rpd.isTransportBinding() && !rmd.isInitiator()) {
            if (rpd.getTransportToken() instanceof HttpsToken) {
                String incomingTransport = rmd.getMsgContext().getIncomingTransportName();
                if (!incomingTransport.equals(org.apache.axis2.Constants.TRANSPORT_HTTPS)) {
                    throw new RampartException("invalidTransport",
                            new String[]{incomingTransport});
                }
                if (((HttpsToken) rpd.getTransportToken()).isRequireClientCertificate()) {

                    MessageContext messageContext = rmd.getMsgContext();
                    HttpServletRequest request = ((HttpServletRequest) messageContext.getProperty(HTTPConstants.MC_HTTP_SERVLETREQUEST));
                    if (request == null || request.getAttribute("javax.servlet.request.X509Certificate") == null) {
                        throw new RampartException("clientAuthRequired");
                    }
                }

            }
        }
    }

    private static Crypto retrieveCryptoFromCache(String cryptoKey, String refreshInterval) {
        // cache hit
        if (cryptoStore.containsKey(cryptoKey)) {
            CachedCrypto cachedCrypto = cryptoStore.get(cryptoKey);
            if (refreshInterval != null) {
                if (cachedCrypto.creationTime + new Long(refreshInterval).longValue() > Calendar
                        .getInstance().getTimeInMillis()) {
                    log.debug("Cache Hit : Crypto Object was found in cache.");
                    return cachedCrypto.crypto;
                } else {
                    log.debug("Cache Miss : Crypto Object found in cache is expired.");
                    return null;
                }
            } else {
                log.debug("Cache Hit : Crypto Object was found in cache.");
                return cachedCrypto.crypto;
            }
        }
        // cache miss
        else {
            log.debug("Cache Miss : Crypto Object was not found in cache.");
            return null;
        }
    }

    private static void cacheCrypto(String cryptoKey, Crypto crypto) {
        cryptoStore.put(cryptoKey, new CachedCrypto(crypto, Calendar.getInstance()
                .getTimeInMillis()));
        log.debug("Crypto object is inserted into the Cache.");

    }

    /**
     * Returns SAML10 Assertion namespace. As follows,
     * http://docs.oasis-open.org/wss/oasis-wss-saml-token-profile-1.0#SAMLAssertionID
     * @return SAML10 assertion namespace.
     */
    public static String getSAML10AssertionNamespace() {

        StringBuilder stringBuilder = new StringBuilder(WSConstants.SAMLTOKEN_NS);
        stringBuilder.append("#").append(WSConstants.SAML_ASSERTION_ID);

        return stringBuilder.toString();

    }

    /**
     * Sets encryption crypto file or crypto reference key to signature crypto file or signature
     * crypto reference.
     * @param msgContext The message context to get signature crypto properties and encryption properties
     * will be set to same message context.
     */
    public static void setEncryptionCrypto(MessageContext msgContext) {
        setEncryptionCryptoFileProperty(msgContext);
        setEncryptionCryptoReferenceProperty(msgContext);
    }

    /**
     * Sets decryption crypto file or crypto reference key to signature crypto file or signature
     * crypto reference.
     * @param msgContext The message context to get signature crypto properties and decryption properties
     * will be set to same message context.
     */
    public static void setDecryptionCrypto(MessageContext msgContext) {
        setDecryptionCryptoFileProperty(msgContext);
        setDecryptionCryptoReferenceProperty(msgContext);
    }

    /**
     * Sets encryption crypto property reference id.- WSHandlerConstants.ENC_PROP_REF_ID
     * @param msgContext The message context.
     */
    private static void setEncryptionCryptoReferenceProperty (MessageContext msgContext) {
        setCryptoProperty(msgContext, WSHandlerConstants.SIG_PROP_REF_ID, WSHandlerConstants.ENC_PROP_REF_ID);
    }

    /**
     * Sets encryption crypto property file.- WSHandlerConstants.DEC_PROP_REF_ID
     * @param msgContext The message context.
     */
    private static void setDecryptionCryptoReferenceProperty (MessageContext msgContext) {
        setCryptoProperty(msgContext, WSHandlerConstants.SIG_PROP_REF_ID, WSHandlerConstants.DEC_PROP_REF_ID);
    }

    /**
     * Sets encryption crypto property file.- WSHandlerConstants.ENC_PROP_FILE
     * @param msgContext The message context.
     */
    private static void setEncryptionCryptoFileProperty (MessageContext msgContext) {
        setCryptoProperty(msgContext, WSHandlerConstants.SIG_PROP_FILE, WSHandlerConstants.ENC_PROP_FILE);
    }

    /**
     * Sets encryption crypto property file.- WSHandlerConstants.DEC_PROP_FILE
     * @param msgContext The message context.
     */
    private static void setDecryptionCryptoFileProperty (MessageContext msgContext) {
        setCryptoProperty(msgContext, WSHandlerConstants.SIG_PROP_FILE, WSHandlerConstants.DEC_PROP_FILE);
    }

    private static void setCryptoProperty(MessageContext msgContext, String signaturePropertyName,
                                          String cryptoPropertyName){

        /**
         * Encryption Crypto is loaded using WSHandlerConstants.ENC_PROP_FILE. If this is not
         * set in the message context set WSHandlerConstants.SIG_PROP_FILE as WSHandlerConstants.ENC_PROP_FILE.
         */
        if (msgContext.getProperty(cryptoPropertyName) == null) {


            String signaturePropertyFile = (String)msgContext.getProperty(signaturePropertyName);

            if (signaturePropertyFile == null) {

                if (log.isDebugEnabled()) {
                    log.debug("Signature crypto property file is not set. Property file key - "
                            + WSHandlerConstants.SIG_PROP_FILE);
                }
            } else {
                msgContext.setProperty(cryptoPropertyName, signaturePropertyFile);
            }
        }
    }

    /**
     * Returns true if needed to encrypt first.
     * @param rpd Rampart policy data
     * @return true if policy says we need to encrypt first else false.
     */
    public static boolean encryptFirst(RampartPolicyData rpd) {
        return SPConstants.ENCRYPT_BEFORE_SIGNING.equals(rpd.getProtectionOrder());
    }

    /**
     * Check if the given SOAP fault reports a security fault.
     * 
     * @param fault
     *            the SOAP fault; must not be <code>null</code>
     * @return <code>true</code> if the fault is a security fault; <code>false</code> otherwise
     */
    public static boolean isSecurityFault(SOAPFault fault) {
        String soapVersionURI = fault.getNamespaceURI();
        SOAPFaultCode code = fault.getCode();
        if (code == null) {
            // If no fault code is given, then it can't be security fault
            return false;
        } else if (soapVersionURI.equals(SOAP11Constants.SOAP_ENVELOPE_NAMESPACE_URI)) {
            return isSecurityFaultCode(code);
        } else {
            // For SOAP 1.2 security faults, the fault code is env:Sender, and the security fault code is
            // specified in the subcode
            SOAPFaultSubCode subCode = code.getSubCode();
            return subCode == null ? false : isSecurityFaultCode(subCode);
        }
    }
    
    private static boolean isSecurityFaultCode(SOAPFaultClassifier code) {
        QName value = code.getValueAsQName();
        return value == null ? false : value.getNamespaceURI().equals(WSConstants.WSSE_NS);
    }
}
