org.wso2.carbon.identity.application.common.util.IdentityApplicationManagementUtil.java Source code

Java tutorial

Introduction

Here is the source code for org.wso2.carbon.identity.application.common.util.IdentityApplicationManagementUtil.java

Source

/*
 * Copyright (c) 2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved.
 *
 * WSO2 Inc. licenses this file to you 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.wso2.carbon.identity.application.common.util;

import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.util.Base64;
import org.apache.axiom.util.base64.Base64Utils;
import org.apache.commons.collections.MapUtils;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.wso2.carbon.claim.mgt.ClaimManagerHandler;
import org.wso2.carbon.identity.application.common.IdentityApplicationManagementException;
import org.wso2.carbon.identity.application.common.model.CertData;
import org.wso2.carbon.identity.application.common.model.ClaimMapping;
import org.wso2.carbon.identity.application.common.model.FederatedAuthenticatorConfig;
import org.wso2.carbon.identity.application.common.model.InboundAuthenticationRequestConfig;
import org.wso2.carbon.identity.application.common.model.Property;
import org.wso2.carbon.identity.application.common.model.ProvisioningConnectorConfig;
import org.wso2.carbon.identity.application.common.model.ServiceProvider;
import org.wso2.carbon.identity.application.common.model.ThreadLocalProvisioningServiceProvider;
import org.wso2.carbon.identity.base.IdentityConstants;
import org.wso2.carbon.identity.base.IdentityException;
import org.wso2.carbon.identity.core.persistence.JDBCPersistenceManager;
import org.wso2.carbon.identity.core.util.IdentityUtil;
import org.wso2.carbon.identity.core.util.IdentityDatabaseUtil;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import javax.xml.namespace.QName;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.SignatureException;
import java.security.cert.Certificate;
import java.security.cert.CertificateEncodingException;
import java.security.cert.CertificateException;
import java.security.cert.CertificateFactory;
import java.security.cert.X509Certificate;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.Set;

public class IdentityApplicationManagementUtil {

    private IdentityApplicationManagementUtil() {
    }

    private static final Log log = LogFactory.getLog(IdentityApplicationManagementUtil.class);
    private static ThreadLocal<ThreadLocalProvisioningServiceProvider> threadLocalProvisioningServiceProvider = new ThreadLocal<ThreadLocalProvisioningServiceProvider>();

    private static final Map<String, String> xmlSignatureAlgorithms;
    private static final Map<String, String> xmlDigestAlgorithms;
    private static final Map<String, String> samlAuthnContextClasses;
    private static final List<String> samlAuthnContextComparisonLevels;

    static {
        //initialize xmlSignatureAlgorithms
        Map<String, String> xmlSignatureAlgorithmMap = new LinkedHashMap<String, String>();
        xmlSignatureAlgorithmMap.put(IdentityApplicationConstants.XML.SignatureAlgorithm.DSA_SHA1,
                IdentityApplicationConstants.XML.SignatureAlgorithmURI.DSA_SHA1);
        xmlSignatureAlgorithmMap.put(IdentityApplicationConstants.XML.SignatureAlgorithm.ECDSA_SHA1,
                IdentityApplicationConstants.XML.SignatureAlgorithmURI.ECDSA_SHA1);
        xmlSignatureAlgorithmMap.put(IdentityApplicationConstants.XML.SignatureAlgorithm.ECDSA_SHA256,
                IdentityApplicationConstants.XML.SignatureAlgorithmURI.ECDSA_SHA256);
        xmlSignatureAlgorithmMap.put(IdentityApplicationConstants.XML.SignatureAlgorithm.ECDSA_SHA384,
                IdentityApplicationConstants.XML.SignatureAlgorithmURI.ECDSA_SHA384);
        xmlSignatureAlgorithmMap.put(IdentityApplicationConstants.XML.SignatureAlgorithm.ECDSA_SHA512,
                IdentityApplicationConstants.XML.SignatureAlgorithmURI.ECDSA_SHA512);
        xmlSignatureAlgorithmMap.put(IdentityApplicationConstants.XML.SignatureAlgorithm.RSA_MD5,
                IdentityApplicationConstants.XML.SignatureAlgorithmURI.RSA_MD5);
        xmlSignatureAlgorithmMap.put(IdentityApplicationConstants.XML.SignatureAlgorithm.RSA_RIPEMD160,
                IdentityApplicationConstants.XML.SignatureAlgorithmURI.RSA_RIPEMD160);
        xmlSignatureAlgorithmMap.put(IdentityApplicationConstants.XML.SignatureAlgorithm.RSA_SHA1,
                IdentityApplicationConstants.XML.SignatureAlgorithmURI.RSA_SHA1);
        xmlSignatureAlgorithmMap.put(IdentityApplicationConstants.XML.SignatureAlgorithm.RSA_SHA256,
                IdentityApplicationConstants.XML.SignatureAlgorithmURI.RSA_SHA256);
        xmlSignatureAlgorithmMap.put(IdentityApplicationConstants.XML.SignatureAlgorithm.RSA_SHA384,
                IdentityApplicationConstants.XML.SignatureAlgorithmURI.RSA_SHA384);
        xmlSignatureAlgorithmMap.put(IdentityApplicationConstants.XML.SignatureAlgorithm.RSA_SHA512,
                IdentityApplicationConstants.XML.SignatureAlgorithmURI.RSA_SHA512);
        xmlSignatureAlgorithms = Collections.unmodifiableMap(xmlSignatureAlgorithmMap);

        //initialize xmlDigestAlgorithms
        Map<String, String> xmlDigestAlgorithmMap = new LinkedHashMap<String, String>();
        xmlDigestAlgorithmMap.put(IdentityApplicationConstants.XML.DigestAlgorithm.MD5,
                IdentityApplicationConstants.XML.DigestAlgorithmURI.MD5);
        xmlDigestAlgorithmMap.put(IdentityApplicationConstants.XML.DigestAlgorithm.RIPEMD160,
                IdentityApplicationConstants.XML.DigestAlgorithmURI.RIPEMD160);
        xmlDigestAlgorithmMap.put(IdentityApplicationConstants.XML.DigestAlgorithm.SHA1,
                IdentityApplicationConstants.XML.DigestAlgorithmURI.SHA1);
        xmlDigestAlgorithmMap.put(IdentityApplicationConstants.XML.DigestAlgorithm.SHA256,
                IdentityApplicationConstants.XML.DigestAlgorithmURI.SHA256);
        xmlDigestAlgorithmMap.put(IdentityApplicationConstants.XML.DigestAlgorithm.SHA384,
                IdentityApplicationConstants.XML.DigestAlgorithmURI.SHA384);
        xmlDigestAlgorithmMap.put(IdentityApplicationConstants.XML.DigestAlgorithm.SHA512,
                IdentityApplicationConstants.XML.DigestAlgorithmURI.SHA512);
        xmlDigestAlgorithms = Collections.unmodifiableMap(xmlDigestAlgorithmMap);

        //initialize samlAuthnContextClasses
        Map<String, String> samlAuthnContextClassMap = new LinkedHashMap<String, String>();
        samlAuthnContextClassMap.put(IdentityApplicationConstants.SAML2.AuthnContextClass.IP,
                IdentityApplicationConstants.SAML2.AuthnContextClassURI.IP);
        samlAuthnContextClassMap.put(IdentityApplicationConstants.SAML2.AuthnContextClass.IP_PASSWORD,
                IdentityApplicationConstants.SAML2.AuthnContextClassURI.IP_PASSWORD);
        samlAuthnContextClassMap.put(IdentityApplicationConstants.SAML2.AuthnContextClass.KERBEROS,
                IdentityApplicationConstants.SAML2.AuthnContextClassURI.KERBEROS);
        samlAuthnContextClassMap.put(
                IdentityApplicationConstants.SAML2.AuthnContextClass.MOBILE_ONE_FACTOR_UNREGISTERED,
                IdentityApplicationConstants.SAML2.AuthnContextClassURI.MOBILE_ONE_FACTOR_UNREGISTERED);
        samlAuthnContextClassMap.put(
                IdentityApplicationConstants.SAML2.AuthnContextClass.MOBILE_TWO_FACTOR_UNREGISTERED,
                IdentityApplicationConstants.SAML2.AuthnContextClassURI.MOBILE_TWO_FACTOR_UNREGISTERED);
        samlAuthnContextClassMap.put(
                IdentityApplicationConstants.SAML2.AuthnContextClass.MOBILE_ONE_FACTOR_CONTRACT,
                IdentityApplicationConstants.SAML2.AuthnContextClassURI.MOBILE_ONE_FACTOR_CONTRACT);
        samlAuthnContextClassMap.put(
                IdentityApplicationConstants.SAML2.AuthnContextClass.MOBILE_TWO_FACTOR_CONTRACT,
                IdentityApplicationConstants.SAML2.AuthnContextClassURI.MOBILE_TWO_FACTOR_CONTRACT);
        samlAuthnContextClassMap.put(IdentityApplicationConstants.SAML2.AuthnContextClass.PASSWORD,
                IdentityApplicationConstants.SAML2.AuthnContextClassURI.PASSWORD);
        samlAuthnContextClassMap.put(
                IdentityApplicationConstants.SAML2.AuthnContextClass.PASSWORD_PROTECTED_TRANSPORT,
                IdentityApplicationConstants.SAML2.AuthnContextClassURI.PASSWORD_PROTECTED_TRANSPORT);
        samlAuthnContextClassMap.put(IdentityApplicationConstants.SAML2.AuthnContextClass.PREVIOUS_SESSION,
                IdentityApplicationConstants.SAML2.AuthnContextClassURI.PREVIOUS_SESSION);
        samlAuthnContextClassMap.put(IdentityApplicationConstants.SAML2.AuthnContextClass.X509,
                IdentityApplicationConstants.SAML2.AuthnContextClassURI.X509);
        samlAuthnContextClassMap.put(IdentityApplicationConstants.SAML2.AuthnContextClass.PGP,
                IdentityApplicationConstants.SAML2.AuthnContextClassURI.PGP);
        samlAuthnContextClassMap.put(IdentityApplicationConstants.SAML2.AuthnContextClass.SPKI,
                IdentityApplicationConstants.SAML2.AuthnContextClassURI.SPKI);
        samlAuthnContextClassMap.put(IdentityApplicationConstants.SAML2.AuthnContextClass.XML_DSIG,
                IdentityApplicationConstants.SAML2.AuthnContextClassURI.XML_DSIG);
        samlAuthnContextClassMap.put(IdentityApplicationConstants.SAML2.AuthnContextClass.SMARTCARD,
                IdentityApplicationConstants.SAML2.AuthnContextClassURI.SMARTCARD);
        samlAuthnContextClassMap.put(IdentityApplicationConstants.SAML2.AuthnContextClass.SMARTCARD_PKI,
                IdentityApplicationConstants.SAML2.AuthnContextClassURI.SMARTCARD_PKI);
        samlAuthnContextClassMap.put(IdentityApplicationConstants.SAML2.AuthnContextClass.SOFTWARE_PKI,
                IdentityApplicationConstants.SAML2.AuthnContextClassURI.SOFTWARE_PKI);
        samlAuthnContextClassMap.put(IdentityApplicationConstants.SAML2.AuthnContextClass.TELEPHONY,
                IdentityApplicationConstants.SAML2.AuthnContextClassURI.TELEPHONY);
        samlAuthnContextClassMap.put(IdentityApplicationConstants.SAML2.AuthnContextClass.NOMAD_TELEPHONY,
                IdentityApplicationConstants.SAML2.AuthnContextClassURI.NOMAD_TELEPHONY);
        samlAuthnContextClassMap.put(IdentityApplicationConstants.SAML2.AuthnContextClass.PERSONAL_TELEPHONY,
                IdentityApplicationConstants.SAML2.AuthnContextClassURI.PERSONAL_TELEPHONY);
        samlAuthnContextClassMap.put(IdentityApplicationConstants.SAML2.AuthnContextClass.AUTHENTICATED_TELEPHONY,
                IdentityApplicationConstants.SAML2.AuthnContextClassURI.AUTHENTICATED_TELEPHONY);
        samlAuthnContextClassMap.put(IdentityApplicationConstants.SAML2.AuthnContextClass.SECURE_REMOTE_PASSWORD,
                IdentityApplicationConstants.SAML2.AuthnContextClassURI.SECURE_REMOTE_PASSWORD);
        samlAuthnContextClassMap.put(IdentityApplicationConstants.SAML2.AuthnContextClass.TLS_CLIENT,
                IdentityApplicationConstants.SAML2.AuthnContextClassURI.TLS_CLIENT);
        samlAuthnContextClassMap.put(IdentityApplicationConstants.SAML2.AuthnContextClass.TIME_SYNC_TOKEN,
                IdentityApplicationConstants.SAML2.AuthnContextClassURI.TIME_SYNC_TOKEN);
        samlAuthnContextClassMap.put(IdentityApplicationConstants.SAML2.AuthnContextClass.UNSPECIFIED,
                IdentityApplicationConstants.SAML2.AuthnContextClassURI.UNSPECIFIED);
        samlAuthnContextClasses = Collections.unmodifiableMap(samlAuthnContextClassMap);

        ////initialize samlAuthnContextComparisonLevels map
        List<String> samlAuthnContextComparisonLevelList = new ArrayList<String>();
        samlAuthnContextComparisonLevelList.add(IdentityApplicationConstants.SAML2.AuthnContextComparison.EXACT);
        samlAuthnContextComparisonLevelList.add(IdentityApplicationConstants.SAML2.AuthnContextComparison.MINIMUM);
        samlAuthnContextComparisonLevelList.add(IdentityApplicationConstants.SAML2.AuthnContextComparison.MAXIMUM);
        samlAuthnContextComparisonLevelList.add(IdentityApplicationConstants.SAML2.AuthnContextComparison.BETTER);
        samlAuthnContextComparisonLevels = Collections.unmodifiableList(samlAuthnContextComparisonLevelList);
    }

    /**
     *
     */
    public static void resetThreadLocalProvisioningServiceProvider() {
        threadLocalProvisioningServiceProvider.remove();
    }

    /**
     * @param serviceProvider
     */
    public static ThreadLocalProvisioningServiceProvider getThreadLocalProvisioningServiceProvider() {
        return threadLocalProvisioningServiceProvider.get();
    }

    /**
     * @param serviceProviderName In-bound - or Just-in-Time provisioning service provider.
     */
    public static void setThreadLocalProvisioningServiceProvider(
            ThreadLocalProvisioningServiceProvider serviceProvider) {
        threadLocalProvisioningServiceProvider.set(serviceProvider);
    }

    /**
     * Validates an URI.
     *
     * @param uriString URI String
     * @return <code>true</code> if valid URI, <code>false</code> otherwise
     */
    public static boolean validateURI(String uriString) {

        if (uriString != null) {
            try {
                URL url = new URL(uriString);
            } catch (MalformedURLException e) {
                log.debug(e.getMessage(), e);
                return false;
            }
        } else {
            String errorMsg = "Invalid URL: \'NULL\'";
            log.debug(errorMsg);
            return false;
        }
        return true;
    }

    /**
     * Utility method to close a database connection
     *
     * @param dbConnection Database <code>Connection</code> object
     */
    public static void closeConnection(Connection dbConnection) {

        IdentityDatabaseUtil.closeConnection(dbConnection);
    }

    /**
     * Utility method to rollback a database connection
     *
     * @param dbConnection Database <code>Connection</code> object
     */
    public static void rollBack(Connection dbConnection) {

        IdentityDatabaseUtil.rollBack(dbConnection);
    }

    /**
     * @param o1
     * @param o2
     * @return
     */
    public static ProvisioningConnectorConfig[] concatArrays(ProvisioningConnectorConfig[] o1,
            ProvisioningConnectorConfig[] o2) {
        ProvisioningConnectorConfig[] ret = new ProvisioningConnectorConfig[o1.length + o2.length];

        System.arraycopy(o1, 0, ret, 0, o1.length);
        System.arraycopy(o2, 0, ret, o1.length, o2.length);

        return ret;
    }

    /**
     * @param o1
     * @param o2
     * @return
     */
    public static Property[] concatArrays(Property[] o1, Property[] o2) {

        Set<Property> properties = new HashSet<Property>(Arrays.asList(o1));
        properties.addAll(Arrays.asList(o2));
        return properties.toArray(new Property[properties.size()]);
    }

    /**
     * @param o1
     * @param o2
     * @return
     */
    public static FederatedAuthenticatorConfig[] concatArrays(FederatedAuthenticatorConfig[] o1,
            FederatedAuthenticatorConfig[] o2) {
        FederatedAuthenticatorConfig[] ret = new FederatedAuthenticatorConfig[o1.length + o2.length];

        System.arraycopy(o1, 0, ret, 0, o1.length);
        System.arraycopy(o2, 0, ret, o1.length, o2.length);

        return ret;
    }

    /**
     * Extract key store filename
     *
     * @param filePath File path of a key store
     * @return Key store file name
     */
    public static String extractKeyStoreFileName(String filePath) {

        if (filePath != null) {
            String name = null;
            int index = filePath.lastIndexOf('/');
            if (index != -1) {
                name = filePath.substring(index + 1);
            } else {
                index = filePath.lastIndexOf(File.separatorChar);
                if (index != -1) {
                    name = filePath.substring(filePath.lastIndexOf(File.separatorChar));
                } else {
                    name = filePath;
                }
            }
            return name;
        } else {
            String errorMsg = "Invalid file path: \'NULL\'";
            log.debug(errorMsg);
            throw new IllegalArgumentException(errorMsg);
        }
    }

    /**
     * Generate thumbprint of certificate
     *
     * @param encodedCert Base64 encoded certificate
     * @return Certificate thumbprint
     * @throws java.security.NoSuchAlgorithmException Unsupported hash algorithm
     */
    public static String generateThumbPrint(String encodedCert) throws NoSuchAlgorithmException {

        if (encodedCert != null) {
            MessageDigest digestValue = null;
            digestValue = MessageDigest.getInstance("SHA-1");
            byte[] der = Base64.decode(encodedCert);
            digestValue.update(der);
            byte[] digestInBytes = digestValue.digest();
            String publicCertThumbprint = hexify(digestInBytes);
            return publicCertThumbprint;
        } else {
            String errorMsg = "Invalid encoded certificate: \'NULL\'";
            log.debug(errorMsg);
            throw new IllegalArgumentException(errorMsg);
        }
    }

    /**
     * Generate thumbprint of certificate
     *
     * @param encodedCert Base64 encoded certificate
     * @return Decoded <code>Certificate</code>
     * @throws java.security.cert.CertificateException Error when decoding certificate
     */
    public static Certificate decodeCertificate(String encodedCert) throws CertificateException {

        if (encodedCert != null) {
            byte[] bytes = Base64.decode(encodedCert);
            CertificateFactory factory = CertificateFactory.getInstance("X.509");
            X509Certificate cert = (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(bytes));
            return cert;
        } else {
            String errorMsg = "Invalid encoded certificate: \'NULL\'";
            log.debug(errorMsg);
            throw new IllegalArgumentException(errorMsg);
        }
    }

    /**
     * >>>>>>> .r201641 Helper method to hexify a byte array. TODO:need to verify the logic
     *
     * @param bytes
     * @return hexadecimal representation
     */
    public static String hexify(byte bytes[]) {

        if (bytes != null) {
            char[] hexDigits = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
            StringBuilder buf = new StringBuilder(bytes.length * 2);
            for (int i = 0; i < bytes.length; ++i) {
                buf.append(hexDigits[(bytes[i] & 0xf0) >> 4]);
                buf.append(hexDigits[bytes[i] & 0x0f]);
            }
            return buf.toString();
        } else {
            String errorMsg = "Invalid byte array: \'NULL\'";
            log.debug(errorMsg);
            throw new IllegalArgumentException(errorMsg);
        }
    }

    /**
     * @param encodedCert
     * @return
     * @throws CertificateException
     */
    public static CertData getCertData(String encodedCert) throws CertificateException {

        if (encodedCert != null) {
            byte[] bytes = Base64.decode(encodedCert);
            CertificateFactory factory = CertificateFactory.getInstance("X.509");
            X509Certificate cert = (X509Certificate) factory.generateCertificate(new ByteArrayInputStream(bytes));
            Format formatter = new SimpleDateFormat("dd/MM/yyyy");
            return fillCertData(cert, formatter);
        } else {
            String errorMsg = "Invalid encoded certificate: \'NULL\'";
            log.debug(errorMsg);
            throw new IllegalArgumentException(errorMsg);
        }
    }

    /**
     * @param array
     * @return
     */
    public static boolean exclusiveOR(boolean[] array) {
        boolean foundTrue = false;
        for (boolean temp : array) {
            if (temp) {
                if (foundTrue) {
                    return false;
                } else {
                    foundTrue = true;
                }
            }
        }
        return foundTrue;
    }

    /**
     * @param cert
     * @param formatter
     * @return
     * @throws CertificateEncodingException
     */
    private static CertData fillCertData(X509Certificate cert, Format formatter)
            throws CertificateEncodingException {

        CertData certData = new CertData();
        certData.setSubjectDN(cert.getSubjectDN().getName());
        certData.setIssuerDN(cert.getIssuerDN().getName());
        certData.setSerialNumber(cert.getSerialNumber());
        certData.setVersion(cert.getVersion());
        certData.setNotAfter(formatter.format(cert.getNotAfter()));
        certData.setNotBefore(formatter.format(cert.getNotBefore()));
        certData.setPublicKey(Base64.encode(cert.getPublicKey().getEncoded()));
        return certData;
    }

    /**
     * @param rs
     */
    public static void closeResultSet(ResultSet rs) {
        IdentityDatabaseUtil.closeResultSet(rs);
    }

    public static void closeStatement(PreparedStatement preparedStatement) {
        IdentityDatabaseUtil.closeStatement(preparedStatement);
    }

    /**
     * @param outboundClaimDialect
     * @param inboundClaimValueMap
     * @param inboundClaimMapping
     * @param outboundClaimValueMapping
     * @param tenantDomainName
     * @return
     * @throws IdentityApplicationManagementException
     */
    public static Map<ClaimMapping, List<String>> getMappedClaims(String outboundClaimDialect,
            Map<String, String> inboundClaimValueMap, ClaimMapping[] inboundClaimMappings,
            Map<ClaimMapping, List<String>> outboundClaimValueMappings, String tenantDomain)
            throws IdentityApplicationManagementException {

        try {

            // we do have in-bound claim mapping - but no out-bound claim mapping - no out-bound
            // default values.since we do not know the out-bound claim mapping - whatever in the
            // in-bound claims will be mapped into the out-bound claim dialect.

            if (MapUtils.isEmpty(inboundClaimValueMap)) {
                // we do not have out-bound claim mapping - and a default values to worry about.
                // just return what we got.
                return outboundClaimValueMappings;
            }

            Map<String, String> claimMap = null;

            // out-bound is not in wso2 carbon dialect. we need to find how it maps to wso2
            // carbon dialect.
            Map<String, String> outBoundToCarbonClaimMapppings = null;

            // we only know the dialect - it is a standard claim dialect.
            // this returns back a map - having carbon claim dialect as the key.
            // null argument is passed - because we do not know the required attributes for
            // out-bound provisioning. This will find carbon claim mappings for the entire out-bound
            // claim dialect.
            outBoundToCarbonClaimMapppings = ClaimManagerHandler.getInstance()
                    .getMappingsMapFromOtherDialectToCarbon(outboundClaimDialect, null, tenantDomain, true);

            if (outBoundToCarbonClaimMapppings == null) {
                // we did not find any carbon claim mappings corresponding to the out-bound claim
                // dialect - we cannot map the in-bound claim dialect to out-bound claim dialect.
                // just return what we got.
                return outboundClaimValueMappings;
            }

            // {in-bound-claim-uri / out-bound-claim-uri
            claimMap = new HashMap<String, String>();

            for (ClaimMapping inboundClaimMapping : inboundClaimMappings) {
                // there can be a claim mapping without a mapped local claim.
                // if that is the case - we cannot map it to an out-bound claim.
                if (inboundClaimMapping.getLocalClaim() == null
                        || inboundClaimMapping.getLocalClaim().getClaimUri() == null) {
                    if (log.isDebugEnabled()) {
                        log.debug("Inbound claim - local claim is null");
                    }
                    continue;
                }

                // get the out-bound claim corresponding to the carbon dialect - which is the key.
                String outboundClaim = outBoundToCarbonClaimMapppings
                        .get(inboundClaimMapping.getLocalClaim().getClaimUri());

                if (outboundClaim != null) {
                    // in-bound claim uri / out-bound claim uri.
                    if (inboundClaimMapping.getRemoteClaim() != null
                            && inboundClaimMapping.getRemoteClaim().getClaimUri() != null) {
                        claimMap.put(inboundClaimMapping.getRemoteClaim().getClaimUri(), outboundClaim);
                    }
                }
            }

            if (claimMap.isEmpty()) {
                // we do not have a claim map.
                // return what we got.
                return outboundClaimValueMappings;
            }

            for (Iterator<Entry<String, String>> iterator = claimMap.entrySet().iterator(); iterator.hasNext();) {
                Entry<String, String> entry = iterator.next();

                String inboundClaimUri = entry.getKey();
                String outboundClaimUri = entry.getValue();
                String claimValue = null;

                if (outboundClaimUri != null) {
                    claimValue = inboundClaimValueMap.get(inboundClaimUri);
                }
                // null value goes there because we do not have an out-bound claim mapping - and
                // also default values.
                if (claimValue != null) {
                    outboundClaimValueMappings.put(
                            ClaimMapping.build(inboundClaimUri, outboundClaimUri, null, false),
                            Arrays.asList(new String[] { claimValue }));
                }
            }

        } catch (Exception e) {
            throw new IdentityApplicationManagementException("Error while loading claim mappings.", e);
        }

        return outboundClaimValueMappings;
    }

    /**
     * @param outboundClaimDialect
     * @param inboundClaimValueMap
     * @param inboundClaimMappingDialect
     * @param outboundClaimValueMapping
     * @return
     * @throws IdentityApplicationManagementException
     */
    public static Map<ClaimMapping, List<String>> getMappedClaims(String outboundClaimDialect,
            Map<String, String> inboundClaimValueMap, String inboundClaimMappingDialect,
            Map<ClaimMapping, List<String>> outboundClaimValueMappings, String tenantDomain)
            throws IdentityApplicationManagementException {

        // we have in-bound claim dialect and out-bound claim dialect. we do not have an in-bound
        // claim mapping or an out-bound claim mapping.

        try {

            if (MapUtils.isEmpty(inboundClaimValueMap)) {
                return outboundClaimValueMappings;
            }

            Map<String, String> claimMap = null;

            if (IdentityApplicationConstants.WSO2CARBON_CLAIM_DIALECT.equals(inboundClaimMappingDialect)) {
                // in-bound dialect is in default carbon dialect.
                // otherDialectURI, carbonClaimURIs, tenantDomain, carbonDialectAsKey
                // this map will have out-bound dialect as the key.
                claimMap = ClaimManagerHandler.getInstance()
                        .getMappingsMapFromOtherDialectToCarbon(outboundClaimDialect, null, tenantDomain, true);
            } else {
                // out-bound is not in wso2 carbon dialect. we need to find how it maps to wso2
                // carbon dialect.
                Map<String, String> inboundToCarbonClaimMaping = null;
                Map<String, String> outBoundToCarbonClaimMappping = null;

                // this will return back the mapped carbon dialect for the in-bound claims in the
                // in-bound provisioning request.
                // the key of this map will be in in-bound claim dialect.
                inboundToCarbonClaimMaping = ClaimManagerHandler.getInstance()
                        .getMappingsMapFromOtherDialectToCarbon(inboundClaimMappingDialect,
                                inboundClaimValueMap.keySet(), tenantDomain, false);

                // we only know the dialect - it is standard claim dialect.
                // this will return back all the wso2 carbon claims mapped to the out-bound dialect.
                // we send null here because we do not know the required claims for out-bound
                // provisioning.
                // the key of this map will be in carbon dialect.
                outBoundToCarbonClaimMappping = ClaimManagerHandler.getInstance()
                        .getMappingsMapFromOtherDialectToCarbon(outboundClaimDialect, null, tenantDomain, true);

                // in-bound dialect / out-bound dialect.
                claimMap = new HashMap<String, String>();

                for (Iterator<Entry<String, String>> iterator = inboundToCarbonClaimMaping.entrySet()
                        .iterator(); iterator.hasNext();) {
                    Entry<String, String> entry = iterator.next();
                    String outboundClaim = outBoundToCarbonClaimMappping.get(entry.getValue());
                    if (outboundClaim != null) {
                        claimMap.put(entry.getKey(), outboundClaim);
                    }
                }
            }

            if (claimMap.isEmpty()) {
                return outboundClaimValueMappings;
            }

            // when we do not defined the claim mapping for out-bound provisioning we iterate
            // through the in-bound provisioning claim map.
            for (Iterator<Entry<String, String>> iterator = claimMap.entrySet().iterator(); iterator.hasNext();) {
                Entry<String, String> entry = iterator.next();
                String outboundClaimUri = entry.getValue();
                String inboundClaimUri = entry.getKey();

                String claimValue = null;

                if (outboundClaimUri != null) {
                    claimValue = inboundClaimValueMap.get(inboundClaimUri);
                }

                if (claimValue != null) {
                    outboundClaimValueMappings.put(
                            ClaimMapping.build(inboundClaimUri, outboundClaimUri, null, false),
                            Arrays.asList(new String[] { claimValue }));
                }
            }

        } catch (Exception e) {
            throw new IdentityApplicationManagementException("Error while loading claim mappings.", e);
        }

        return outboundClaimValueMappings;
    }

    /**
     * @param outboundClaimMapping
     * @param inboundClaimValueMap
     * @param inboundClaimMapping
     * @param outboundClaimValueMapping
     * @return
     * @throws IdentityApplicationManagementException
     */
    public static Map<ClaimMapping, List<String>> getMappedClaims(ClaimMapping[] outboundClaimMappings,
            Map<String, String> inboundClaimValueMap, ClaimMapping[] inboundClaimMappings,
            Map<ClaimMapping, List<String>> outboundClaimValueMappings)
            throws IdentityApplicationManagementException {

        try {

            // we have in-bound claim mapping and out-bound claim mapping.

            if (outboundClaimValueMappings == null) {
                outboundClaimValueMappings = new HashMap<ClaimMapping, List<String>>();
            }

            if (MapUtils.isEmpty(inboundClaimValueMap)) {
                // we do not have any values in the incoming provisioning request.
                // we need to populate outboundClaimValueMappings map with the default values from
                // the out-bound claim mapping.
                if (outboundClaimMappings != null && outboundClaimMappings.length > 0) {
                    for (ClaimMapping mapping : outboundClaimMappings) {
                        if (mapping.getDefaultValue() != null) {
                            outboundClaimValueMappings.put(mapping,
                                    Arrays.asList(new String[] { mapping.getDefaultValue() }));
                        }
                    }
                }

                return outboundClaimValueMappings;
            }

            if (outboundClaimMappings == null || outboundClaimMappings.length == 0) {
                // we cannot find out-bound claim dialect - return what we have.
                return outboundClaimValueMappings;
            }

            Map<String, String> claimMap = null;

            // out-bound is not in wso2 carbon dialect. we need to find how it maps to wso2
            // carbon dialect.
            Map<String, String> inboundToCarbonClaimMaping = new HashMap<String, String>();
            Map<String, String> outBoundToCarbonClaimMappping = new HashMap<String, String>();

            Map<String, String> outboundClaimDefaultValues = new HashMap<String, String>();

            for (ClaimMapping inboundClaimMapping : inboundClaimMappings) {
                // populate map with in-bound claims.
                if (inboundClaimMapping.getLocalClaim() != null) {
                    inboundToCarbonClaimMaping.put(inboundClaimMapping.getLocalClaim().getClaimUri(),
                            inboundClaimMapping.getRemoteClaim().getClaimUri());
                } else {
                    // ignore. if you do not have a local claim we cannot map it.
                }
            }

            for (ClaimMapping outboundClaimMapping : outboundClaimMappings) {
                // populate a map with the out-bound claims.
                // use remote claim uri as the key.
                if (outboundClaimMapping.getLocalClaim() != null) {
                    outBoundToCarbonClaimMappping.put(outboundClaimMapping.getRemoteClaim().getClaimUri(),
                            outboundClaimMapping.getLocalClaim().getClaimUri());
                } else {
                    outBoundToCarbonClaimMappping.put(outboundClaimMapping.getRemoteClaim().getClaimUri(), null);
                }

                outboundClaimDefaultValues.put(outboundClaimMapping.getRemoteClaim().getClaimUri(),
                        outboundClaimMapping.getDefaultValue());
            }

            claimMap = new HashMap<String, String>();

            // we need to have everything in the out-bound claim dialect in the claimMap.
            for (Iterator<Entry<String, String>> iterator = outBoundToCarbonClaimMappping.entrySet()
                    .iterator(); iterator.hasNext();) {
                Entry<String, String> entry = iterator.next();

                String localClaimUri = entry.getValue();
                String outboundClaimUri = entry.getKey();

                String inboundClaim = inboundToCarbonClaimMaping.get(localClaimUri);
                claimMap.put(outboundClaimUri, inboundClaim);
            }

            if (claimMap.isEmpty()) {
                return outboundClaimValueMappings;
            }

            for (Iterator<Entry<String, String>> iterator = claimMap.entrySet().iterator(); iterator.hasNext();) {

                Entry<String, String> entry = iterator.next();
                String outboundClaimUri = entry.getKey();
                String inboundClaimUri = entry.getValue();

                if (inboundClaimUri != null && inboundClaimValueMap.get(inboundClaimUri) != null) {
                    outboundClaimValueMappings.put(
                            ClaimMapping.build(inboundClaimUri, outboundClaimUri,
                                    outboundClaimDefaultValues.get(outboundClaimUri), false),
                            Arrays.asList(new String[] { inboundClaimValueMap.get(inboundClaimUri) }));
                } else {
                    outboundClaimValueMappings.put(
                            ClaimMapping.build(inboundClaimUri, outboundClaimUri,
                                    outboundClaimDefaultValues.get(outboundClaimUri), false),
                            Arrays.asList(new String[] { outboundClaimDefaultValues.get(outboundClaimUri) }));
                }
            }

        } catch (Exception e) {
            throw new IdentityApplicationManagementException("Error while loading claim mappings.", e);
        }

        return outboundClaimValueMappings;
    }

    /**
     * @param outboundClaimMapping
     * @param inboundClaimValueMap
     * @param inboundClaimMappingDialect
     * @param outboundClaimValueMapping
     * @return
     * @throws IdentityApplicationManagementException
     */
    public static Map<ClaimMapping, List<String>> getMappedClaims(ClaimMapping[] outboundClaimMappings,
            Map<String, String> inboundClaimValueMap, String inboundClaimMappingDialect,
            Map<ClaimMapping, List<String>> outboundClaimValueMappings, String tenantDomain)
            throws IdentityApplicationManagementException {

        // we know the out-bound claim mapping - and the in-bound claim dialect.

        try {

            if (MapUtils.isEmpty(inboundClaimValueMap)) {
                // we do not have any values in the incoming provisioning request.
                // we need to populate outboundClaimValueMappings map with the default values from
                // the out-bound claim mapping.
                if (outboundClaimMappings != null && outboundClaimMappings.length > 0) {
                    for (ClaimMapping mapping : outboundClaimMappings) {
                        if (mapping.getDefaultValue() != null) {
                            outboundClaimValueMappings.put(mapping,
                                    Arrays.asList(new String[] { mapping.getDefaultValue() }));
                        }
                    }
                }

                return outboundClaimValueMappings;
            }

            if (outboundClaimMappings == null || outboundClaimMappings.length == 0) {
                // we cannot find out-bound claim dialect - return what we have.
                return outboundClaimValueMappings;
            }

            Map<String, String> claimMap = null;

            // out-bound is not in wso2 carbon dialect. we need to find how it maps to wso2
            // carbon dialect.
            Map<String, String> carbonToInboundClaimMapping = null;

            // we only know the dialect - it is standard claim dialect.
            // returns the carbon claim mapping corresponding to claims in the the in-bound
            // provisioning request with carbon in-bound claim uris as the key.
            carbonToInboundClaimMapping = ClaimManagerHandler.getInstance().getMappingsMapFromOtherDialectToCarbon(
                    inboundClaimMappingDialect, inboundClaimValueMap.keySet(), tenantDomain, true);

            claimMap = new HashMap<String, String>();

            Map<String, String> outboundClaimDefaultValues = new HashMap<String, String>();

            for (ClaimMapping outboundClaimMapping : outboundClaimMappings) {

                String inboundClaim = null;

                if (outboundClaimMapping.getLocalClaim() != null) {
                    inboundClaim = carbonToInboundClaimMapping
                            .get(outboundClaimMapping.getLocalClaim().getClaimUri());
                }

                claimMap.put(outboundClaimMapping.getRemoteClaim().getClaimUri(), inboundClaim);

                outboundClaimDefaultValues.put(outboundClaimMapping.getRemoteClaim().getClaimUri(),
                        outboundClaimMapping.getDefaultValue());

            }

            if (claimMap.isEmpty()) {
                return outboundClaimValueMappings;
            }

            for (Iterator<Entry<String, String>> iterator = claimMap.entrySet().iterator(); iterator.hasNext();) {
                Entry<String, String> entry = iterator.next();
                String outboundClaimUri = entry.getKey();
                String inboundClaimUri = entry.getValue();

                if (inboundClaimUri != null && inboundClaimValueMap.get(inboundClaimUri) != null) {
                    outboundClaimValueMappings.put(
                            ClaimMapping.build(inboundClaimUri, outboundClaimUri,
                                    outboundClaimDefaultValues.get(outboundClaimUri), false),
                            Arrays.asList(new String[] { inboundClaimValueMap.get(inboundClaimUri) }));
                } else {
                    outboundClaimValueMappings.put(
                            ClaimMapping.build(inboundClaimUri, outboundClaimUri,
                                    outboundClaimDefaultValues.get(outboundClaimUri), false),
                            Arrays.asList(new String[] { outboundClaimDefaultValues.get(outboundClaimUri) }));
                }
            }

        } catch (Exception e) {
            throw new IdentityApplicationManagementException("Error while loading claim mappings.", e);
        }

        return outboundClaimValueMappings;
    }

    /**
     * @param configElem
     * @return
     */
    public static Properties readProperties(OMElement configElem) {

        Properties properties = new Properties();
        OMElement propsElem = configElem.getFirstChildWithName(
                getQNameWithIdentityApplicationNS(IdentityApplicationConstants.ConfigElements.PROPERTIES));
        if (propsElem != null) {
            Iterator propItr = propsElem
                    .getChildrenWithLocalName(IdentityApplicationConstants.ConfigElements.PROPERTY);
            for (; propItr.hasNext();) {
                OMElement propElem = (OMElement) propItr.next();
                String propName = propElem
                        .getAttributeValue(new QName(IdentityApplicationConstants.ConfigElements.ATTR_NAME)).trim();
                String propValue = propElem.getText().trim();
                properties.put(propName, propValue);
                if (log.isDebugEnabled()) {
                    log.debug("Property name : " + propName + ", Property Value : " + propValue);
                }
            }
        }
        return properties;
    }

    /**
     * @param localPart
     * @return
     */
    public static QName getQNameWithIdentityApplicationNS(String localPart) {
        return new QName(IdentityApplicationConstants.APPLICATION_AUTHENTICATION_DEFAULT_NAMESPACE, localPart);
    }

    /**
     * @param federatedAuthenticators
     * @param authenticatorName
     * @return
     */
    public static FederatedAuthenticatorConfig getFederatedAuthenticator(
            FederatedAuthenticatorConfig[] federatedAuthenticators, String authenticatorName) {

        for (FederatedAuthenticatorConfig authenticator : federatedAuthenticators) {
            if (authenticator.getName().equals(authenticatorName)) {
                return authenticator;
            }
        }
        return null;
    }

    /**
     * @param provisioningConnectors
     * @param connectorType
     * @return
     */
    public static ProvisioningConnectorConfig getProvisioningConnector(
            ProvisioningConnectorConfig[] provisioningConnectors, String connectorType) {

        for (ProvisioningConnectorConfig connector : provisioningConnectors) {
            if (connector.getName().equals(connectorType)) {
                return connector;
            }
        }
        return null;
    }

    public static Property getProperty(Property[] properties, String propertyName) {

        for (Property property : properties) {
            if (property.getName().equals(propertyName)) {
                return property;
            }
        }
        return null;
    }

    /**
     * @param jsonObj
     * @return Base64 encoded JWT
     */
    public static String getSignedJWT(String jsonObj, ServiceProvider serviceProvider) {

        String oauthConsumerSecret = null;

        if (serviceProvider.getInboundAuthenticationConfig() != null
                && serviceProvider.getInboundAuthenticationConfig().getInboundAuthenticationRequestConfigs() != null
                && serviceProvider.getInboundAuthenticationConfig()
                        .getInboundAuthenticationRequestConfigs().length > 0) {

            InboundAuthenticationRequestConfig[] authReqConfigs = serviceProvider.getInboundAuthenticationConfig()
                    .getInboundAuthenticationRequestConfigs();

            for (InboundAuthenticationRequestConfig authReqConfig : authReqConfigs) {
                if ("oauth2".equals(authReqConfig.getInboundAuthType())) {
                    if (authReqConfig.getProperties() != null) {
                        for (Property property : authReqConfig.getProperties()) {
                            if ("oauthConsumerSecret".equalsIgnoreCase(property.getName())) {
                                oauthConsumerSecret = property.getValue();
                                break;
                            }
                        }
                    }
                }
            }

        }

        String jwtBody = "{\"iss\":\"wso2\",\"exp\":" + new Date().getTime() + 3000 + ",\"iat\":"
                + new Date().getTime() + "," + jsonObj + "}";
        String jwtHeader = "{\"typ\":\"JWT\", \"alg\":\"HS256\"}";

        if (oauthConsumerSecret == null) {
            jwtHeader = "{\"typ\":\"JWT\", \"alg\":\"none\"}";
        }

        String base64EncodedHeader = Base64Utils.encode(jwtHeader.getBytes());
        String base64EncodedBody = Base64Utils.encode(jwtBody.getBytes());

        if (log.isDebugEnabled()) {
            log.debug("JWT Header :" + jwtHeader);
            log.debug("JWT Body :" + jwtBody);
        }

        String assertion = base64EncodedHeader + "." + base64EncodedBody;

        if (oauthConsumerSecret == null) {
            return assertion + ".";
        } else {
            String signedAssertion;
            try {
                signedAssertion = calculateHmacSha1(oauthConsumerSecret, assertion);
                return assertion + "." + signedAssertion;
            } catch (SignatureException e) {
                log.error("Error while siging the assertion", e);
                return assertion + ".";
            }
        }
    }

    /**
     * @param key
     * @param value
     * @return
     * @throws SignatureException
     */
    public static String calculateHmacSha1(String key, String value) throws SignatureException {
        String result;
        try {
            SecretKeySpec signingKey = new SecretKeySpec(key.getBytes(), "HmacSHA1");
            Mac mac = Mac.getInstance("HmacSHA1");
            mac.init(signingKey);
            byte[] rawHmac = mac.doFinal(value.getBytes());
            result = Base64Utils.encode(rawHmac);
        } catch (Exception e) {
            if (log.isDebugEnabled()) {
                log.debug("Failed to create the HMAC Signature", e);
            }
            throw new SignatureException("Failed to calculate HMAC : " + e.getMessage());
        }
        return result;
    }

    public static Map<String, String> getXMLSignatureAlgorithms() {
        return xmlSignatureAlgorithms;
    }

    public static Map<String, String> getXMLDigestAlgorithms() {
        return xmlDigestAlgorithms;
    }

    public static Map<String, String> getSAMLAuthnContextClasses() {
        return samlAuthnContextClasses;
    }

    public static List<String> getSAMLAuthnContextComparisonLevels() {
        return samlAuthnContextComparisonLevels;
    }

    public static Set<String> getXMLSignatureAlgorithmNames() {
        return xmlSignatureAlgorithms.keySet();
    }

    public static Set<String> getXMLDigestAlgorithmNames() {
        return xmlDigestAlgorithms.keySet();
    }

    public static Set<String> getSAMLAuthnContextClassNames() {
        return samlAuthnContextClasses.keySet();
    }

    public static String getSigningAlgoURIByConfig() {
        if (StringUtils.isNotBlank(
                IdentityUtil.getProperty(IdentityConstants.ServerConfig.SSO_DEFAULT_SIGNING_ALGORITHM))) {
            return IdentityUtil.getProperty(IdentityConstants.ServerConfig.SSO_DEFAULT_SIGNING_ALGORITHM).trim();
        } else {
            return IdentityApplicationConstants.XML.SignatureAlgorithmURI.RSA_SHA1;
        }
    }

    public static String getDigestAlgoURIByConfig() {
        if (StringUtils.isNotBlank(
                IdentityUtil.getProperty(IdentityConstants.ServerConfig.SSO_DEFAULT_DIGEST_ALGORITHM))) {
            return IdentityUtil.getProperty(IdentityConstants.ServerConfig.SSO_DEFAULT_DIGEST_ALGORITHM).trim();
        } else {
            return IdentityApplicationConstants.XML.DigestAlgorithmURI.SHA1;
        }
    }
}