org.gluu.oxtrust.ldap.service.Shibboleth3ConfService.java Source code

Java tutorial

Introduction

Here is the source code for org.gluu.oxtrust.ldap.service.Shibboleth3ConfService.java

Source

/*
 * oxTrust is available under the MIT License (2008). See http://opensource.org/licenses/MIT for full text.
 *
 * Copyright (c) 2016, Gluu
 */
package org.gluu.oxtrust.ldap.service;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.validation.Schema;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.apache.commons.httpclient.protocol.Protocol;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.apache.velocity.VelocityContext;
import org.gluu.oxtrust.config.OxTrustConfiguration;
import org.gluu.oxtrust.model.GluuCustomAttribute;
import org.gluu.oxtrust.model.GluuMetadataSourceType;
import org.gluu.oxtrust.model.GluuSAMLFederationProposal;
import org.gluu.oxtrust.model.GluuSAMLTrustRelationship;
import org.gluu.oxtrust.model.ProfileConfiguration;
import org.gluu.oxtrust.model.SubversionFile;
import org.gluu.oxtrust.util.EasyCASSLProtocolSocketFactory;
import org.gluu.saml.metadata.SAMLMetadataParser;
import org.gluu.oxtrust.util.OxTrustConstants;
import org.jboss.seam.Component;
import org.jboss.seam.ScopeType;
import org.jboss.seam.annotations.AutoCreate;
import org.jboss.seam.annotations.In;
import org.jboss.seam.annotations.Logger;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.annotations.Scope;
import org.jboss.seam.log.Log;
import org.opensaml.xml.schema.SchemaBuilder;
import org.opensaml.xml.schema.SchemaBuilder.SchemaLanguage;
import org.w3c.dom.Document;
import org.xdi.config.oxtrust.ApplicationConfiguration;
import org.xdi.ldap.model.GluuStatus;
import org.xdi.model.GluuAttribute;
import org.xdi.model.GluuUserRole;
import org.xdi.model.SchemaEntry;
import org.xdi.service.SchemaService;
import org.xdi.util.INumGenerator;
import org.xdi.util.StringHelper;
import org.xdi.util.Util;
import org.xdi.util.exception.InvalidConfigurationException;
import org.xdi.util.io.FileUploadWrapper;
import org.xdi.util.io.HTTPFileDownloader;
import org.xdi.util.security.StringEncrypter;
import org.xdi.util.security.StringEncrypter.EncryptionException;
import org.xml.sax.InputSource;
import org.xml.sax.SAXException;

import com.unboundid.ldap.sdk.schema.AttributeTypeDefinition;
import org.xdi.xml.GluuErrorHandler;
import org.xdi.xml.XMLValidator;

/**
 * Provides operations with attributes
 * 
 * @author Dmitry Ognyannikov, 2016
 */
@Scope(ScopeType.STATELESS)
@Name("shibboleth3ConfService")
@AutoCreate
public class Shibboleth3ConfService implements Serializable {

    private static final long serialVersionUID = 6752452480800274694L;

    private static final String SHIB3_IDP = "idp";
    private static final String SHIB3_SP = "sp";

    private static final String SHIB3_IDP_CONF_FOLDER = "conf";
    public static final String SHIB3_IDP_METADATA_FOLDER = "metadata";

    private static final String SHIB3_IDP_ATTRIBUTE_FILTER_FILE = "attribute-filter.xml";
    private static final String SHIB3_IDP_ATTRIBUTE_RESOLVER_FILE = "attribute-resolver.xml";
    private static final String SHIB3_IDP_RELYING_PARTY = "relying-party.xml";
    private static final String SHIB3_IDP_PROFILE_HADLER = "handler.xml";
    public static final String SHIB3_IDP_IDP_METADATA_FILE = "idp-metadata.xml";
    public static final String SHIB3_IDP_SP_METADATA_FILE = "sp-metadata.xml";
    public static final String SHIB3_SP_ATTRIBUTE_MAP = "attribute-map.xml";
    public static final String SHIB3_SP_SHIBBOLETH2 = "shibboleth2.xml";
    private static final String SHIB3_SP_READ_ME = "WEB-INF/resources/doc/README_SP.pdf";
    private static final String SHIB3_SP_READ_ME_WINDOWS = "WEB-INF/resources/doc/README_SP_windows.pdf";

    private static final String SHIB3_SP_METADATA_FILE_PATTERN = "%s-sp-metadata.xml";
    private static final String SHIB3_IDP_METADATA_FILE_PATTERN = "%s-idp-metadata.xml";

    public static final String PUBLIC_CERTIFICATE_START_LINE = "-----BEGIN CERTIFICATE-----";
    public static final String PUBLIC_CERTIFICATE_END_LINE = "-----END CERTIFICATE-----";

    public static final String PRIVATE_KEY_START_LINE = "-----BEGIN RSA PRIVATE KEY-----";
    public static final String PRIVATE_KEY_END_LINE = "-----END RSA PRIVATE KEY-----";

    private static final String SHIB3_IDP_LOGIN_CONFIG_FILE = "login.config";

    private static final String SHIB3_IDP_METADATA_CREDENTIALS_FOLDER = SHIB3_IDP_METADATA_FOLDER + File.separator
            + "credentials";

    private static final String SHIB3_METADATA_FILE_PATTERN = "%s-metadata.xml";

    public static final String SHIB3_IDP_TEMPMETADATA_FOLDER = "temp_metadata";

    public static final String SHIB3_IDP_SP_KEY_FILE = "spkey.key";

    public static final String SHIB3_IDP_SP_CERT_FILE = "spcert.crt";

    @In
    private AttributeService attributeService;

    @In
    private TemplateService templateService;

    @Logger
    private Log log;

    @In
    private FilterService filterService;

    @In(value = "#{oxTrustConfiguration.applicationConfiguration}")
    private ApplicationConfiguration applicationConfiguration;

    @In(value = "#{oxTrustConfiguration.cryptoConfigurationSalt}")
    private String cryptoConfigurationSalt;

    /*
     * Generate relying-party.xml, attribute-filter.xml, attribute-resolver.xml
     */
    public boolean generateConfigurationFiles(List<GluuSAMLTrustRelationship> trustRelationships) {
        //TODO: change for IDP3 

        if (applicationConfiguration.getShibboleth2IdpRootDir() == null) {
            throw new InvalidConfigurationException(
                    "Failed to update configuration due to undefined IDP root folder");
        }

        String idpConfFolder = applicationConfiguration.getShibboleth2IdpRootDir() + File.separator
                + SHIB3_IDP_CONF_FOLDER + File.separator;
        String idpMetadataFolder = applicationConfiguration.getShibboleth2IdpRootDir() + File.separator
                + SHIB3_IDP_METADATA_FOLDER + File.separator;

        // Prepare data for files
        initAttributes(trustRelationships);
        HashMap<String, Object> trustParams = initTrustParamMap(trustRelationships);
        HashMap<String, Object> attrParams = initAttributeParamMap(trustRelationships);

        boolean result = (trustParams != null) && (attrParams != null);
        if (!result) {
            return result;
        }

        VelocityContext context = prepareVelocityContext(trustParams, attrParams, idpMetadataFolder);

        // Generate attribute-resolver.xml
        String attributeResolver = templateService.generateConfFile(SHIB3_IDP_ATTRIBUTE_RESOLVER_FILE, context);
        // Generate attribute-filter.xml
        String attributeFilter = templateService.generateConfFile(SHIB3_IDP_ATTRIBUTE_FILTER_FILE, context);
        // Generate relying-party.xml
        String relyingParty = templateService.generateConfFile(SHIB3_IDP_RELYING_PARTY, context);
        // Generate shibboleth2.xml
        String shibConfig = templateService.generateConfFile(SHIB3_SP_SHIBBOLETH2, context);
        // Generate handler.xml
        String profileHandler = templateService.generateConfFile(SHIB3_IDP_PROFILE_HADLER, context);

        // Generate attribute-map.xml
        // String attributeMap =
        // templateService.generateConfFile(SHIB2_SP_ATTRIBUTE_MAP, context);

        result = (attributeFilter != null) && (attributeResolver != null) && (relyingParty != null)
                && (shibConfig != null) && (profileHandler != null);

        // Write attribute-resolver.xml
        result &= templateService.writeConfFile(idpConfFolder + SHIB3_IDP_ATTRIBUTE_RESOLVER_FILE,
                attributeResolver);
        // Write attribute-filter.xml
        result &= templateService.writeConfFile(idpConfFolder + SHIB3_IDP_ATTRIBUTE_FILTER_FILE, attributeFilter);
        // Write relying-party.xml
        result &= templateService.writeConfFile(idpConfFolder + SHIB3_IDP_RELYING_PARTY, relyingParty);
        // Write shibboleth2.xml
        result &= templateService.writeConfFile(getSpShibboleth3FilePath(), shibConfig);
        // Write handler.xml
        result &= templateService.writeConfFile(idpConfFolder + SHIB3_IDP_PROFILE_HADLER, profileHandler);

        // Write attribute-map.xml
        // result &= templateService.writeConfFile(spConfFolder +
        // SHIB2_SP_ATTRIBUTE_MAP, attributeMap);

        return result;
    }

    /*
     * Init attributes
     */
    private void initAttributes(List<GluuSAMLTrustRelationship> trustRelationships) {
        //TODO: change for IDP3

        List<GluuAttribute> attributes = attributeService.getAllPersonAttributes(GluuUserRole.ADMIN);
        HashMap<String, GluuAttribute> attributesByDNs = attributeService.getAttributeMapByDNs(attributes);

        GluuAttribute uid = attributeService.getAttributeByName(OxTrustConstants.uid);

        // Load attributes definition
        for (GluuSAMLTrustRelationship trustRelationship : trustRelationships) {
            // Add first attribute uid
            List<String> oldAttributes = trustRelationship.getReleasedAttributes();
            List<String> releasedAttributes = new ArrayList<String>();
            if (oldAttributes != null) {
                releasedAttributes.addAll(oldAttributes);
            }

            if (uid != null) {
                if (releasedAttributes.remove(uid.getDn())) {
                    releasedAttributes.add(0, uid.getDn());
                }
            }

            // Resolve custom attributes by DNs
            trustRelationship.setReleasedCustomAttributes(
                    attributeService.getCustomAttributesByAttributeDNs(releasedAttributes, attributesByDNs));

            // Set attribute meta-data
            attributeService.setAttributeMetadata(trustRelationship.getReleasedCustomAttributes(), attributes);
        }
    }

    /*
     * Prepare trustRelationships to generate files
     */
    private HashMap<String, Object> initTrustParamMap(List<GluuSAMLTrustRelationship> trustRelationships) {
        //TODO: change for IDP3

        log.trace("Starting trust parameters map initialization.");
        HashMap<String, Object> trustParams = new HashMap<String, Object>();

        // Metadata signature verification engines
        // https://wiki.shibboleth.net/confluence/display/SHIB2/IdPTrustEngine
        List<Map<String, String>> trustEngines = new ArrayList<Map<String, String>>();

        // the map of {inum,number} for easy naming of relying parties.
        Map<String, String> trustIds = new HashMap<String, String>();

        // Trust relationships that are part of some federation
        List<GluuSAMLTrustRelationship> deconstructed = new ArrayList<GluuSAMLTrustRelationship>();
        // the map of {inum,number} for easy naming of federated relying
        // parties.
        Map<String, String> deconstructedIds = new HashMap<String, String>();
        // the map of {inum, {inum, inum, inum...}} describing the federations
        // and TRs defined from them.
        Map<String, List<String>> deconstructedMap = new HashMap<String, List<String>>();
        // entityIds defined in each TR.
        Map<String, List<String>> trustEntityIds = new HashMap<String, List<String>>();
        int id = 1;
        for (GluuSAMLTrustRelationship trustRelationship : trustRelationships) {
            boolean isPartOfFederation = !(trustRelationship.getSpMetaDataSourceType() == GluuMetadataSourceType.URI
                    || trustRelationship.getSpMetaDataSourceType() == GluuMetadataSourceType.FILE);
            if (!isPartOfFederation) {
                // Set Id
                trustIds.put(trustRelationship.getInum(), String.valueOf(id++));

                // Set entityId
                String idpMetadataFolder = applicationConfiguration.getShibboleth2IdpRootDir() + File.separator
                        + SHIB3_IDP_METADATA_FOLDER + File.separator;
                File metadataFile = new File(idpMetadataFolder + trustRelationship.getSpMetaDataFN());
                List<String> entityIds = SAMLMetadataParser.getEntityIdFromMetadataFile(metadataFile);
                // if for some reason metadata is corrupted or missing - mark
                // trust relationship INACTIVE
                // user will be able to fix this in UI
                if (entityIds == null) {
                    trustRelationship.setStatus(GluuStatus.INACTIVE);
                    TrustService.instance().updateTrustRelationship(trustRelationship);
                    continue;
                }

                trustEntityIds.put(trustRelationship.getInum(), entityIds);
                try {
                    filterService.parseFilters(trustRelationship);
                    ProfileConfigurationService.instance().parseProfileConfigurations(trustRelationship);
                } catch (Exception e) {
                    log.error("Failed to parse stored metadataFilter configuration for trustRelationship "
                            + trustRelationship.getDn(), e);
                }
                if (trustRelationship.getMetadataFilters().get("signatureValidation") != null) {
                    Map<String, String> trustEngine = new HashMap<String, String>();
                    trustEngine.put("id", "Trust" + StringHelper.removePunctuation(trustRelationship.getInum()));
                    trustEngine.put("certPath",
                            applicationConfiguration.getShibboleth2IdpRootDir() + File.separator
                                    + SHIB3_IDP_METADATA_FOLDER + File.separator + "credentials" + File.separator
                                    + trustRelationship.getMetadataFilters().get("signatureValidation")
                                            .getFilterCertFileName());
                    trustEngines.add(trustEngine);
                }

                // If there is an intrusive filter - push it to the end of the
                // list.
                if (trustRelationship.getGluuSAMLMetaDataFilter() != null) {
                    List<String> filtersList = new ArrayList<String>();
                    String entityRoleWhiteList = null;
                    for (String filterXML : trustRelationship.getGluuSAMLMetaDataFilter()) {
                        Document xmlDocument = null;
                        try {
                            xmlDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder()
                                    .parse(new java.io.ByteArrayInputStream(filterXML.getBytes()));
                        } catch (Exception e) {
                            log.error("GluuSAMLMetaDataFilter contains invalid value.", e);
                            continue;
                        }

                        if (xmlDocument.getFirstChild().getAttributes().getNamedItem("xsi:type").getNodeValue()
                                .equals(FilterService.ENTITY_ROLE_WHITE_LIST_TYPE)) {
                            entityRoleWhiteList = filterXML;
                            continue;
                        }
                        filtersList.add(filterXML);
                    }
                    if (entityRoleWhiteList != null) {
                        filtersList.add(entityRoleWhiteList);
                    }
                    trustRelationship.setGluuSAMLMetaDataFilter(filtersList);
                }
            } else {
                String federationInum = trustRelationship.getContainerFederation().getInum();
                if (deconstructedMap.get(federationInum) == null) {
                    deconstructedMap.put(federationInum, new ArrayList<String>());
                }
                deconstructedMap.get(federationInum).add(trustRelationship.getEntityId());
                deconstructed.add(trustRelationship);
                deconstructedIds.put(trustRelationship.getEntityId(), String.valueOf(id++));
            }

        }
        for (String trustRelationshipInum : trustEntityIds.keySet()) {
            List<String> federatedSites = deconstructedMap.get(trustRelationshipInum);
            if (federatedSites != null) {
                trustEntityIds.get(trustRelationshipInum).removeAll(federatedSites);
            }
        }

        trustParams.put("idpCredentialsPath", applicationConfiguration.getShibboleth2IdpRootDir() + File.separator
                + SHIB3_IDP_METADATA_FOLDER + File.separator + "credentials" + File.separator);

        trustParams.put("deconstructed", deconstructed);
        trustParams.put("deconstructedIds", deconstructedIds);

        trustParams.put("trustEngines", trustEngines);
        trustParams.put("trusts", trustRelationships);
        trustParams.put("trustIds", trustIds);
        trustParams.put("trustEntityIds", trustEntityIds);

        return trustParams;
    }

    private HashMap<String, Object> initAttributeParamMap(List<GluuSAMLTrustRelationship> trustRelationships) {
        //TODO: change for IDP3

        HashMap<String, Object> attrParams = new HashMap<String, Object>();
        // Collect attributes
        List<GluuAttribute> attributes = new ArrayList<GluuAttribute>();
        List<String> attributeNames = new ArrayList<String>();
        for (GluuSAMLTrustRelationship trustRelationship : trustRelationships) {
            for (GluuCustomAttribute customAttribute : trustRelationship.getReleasedCustomAttributes()) {
                GluuAttribute metadata = customAttribute.getMetadata();
                if (!attributes.contains(metadata)) {
                    attributes.add(metadata);
                    String attributeName = metadata.getName();
                    attributeNames.add(attributeName);
                }
            }
        }

        SchemaService shemaService = SchemaService.instance();
        SchemaEntry schemaEntry = shemaService.getSchema();
        List<AttributeTypeDefinition> attributeTypes = shemaService.getAttributeTypeDefinitions(schemaEntry,
                attributeNames);

        Map<String, String> attributeSAML1Strings = new HashMap<String, String>();
        Map<String, String> attributeSAML2Strings = new HashMap<String, String>();
        for (GluuAttribute metadata : attributes) {
            String attributeName = metadata.getName();

            AttributeTypeDefinition attributeTypeDefinition = shemaService
                    .getAttributeTypeDefinition(attributeTypes, attributeName);
            if (attributeTypeDefinition == null) {
                log.error("Failed to get OID for attribute name {0}", attributeName);
                return null;
            }
            //
            // urn::dir:attribute-def:$attribute.name
            // urn:oid:$attrParams.attributeOids.get($attribute.name)
            String saml1String = metadata.getSaml1Uri();
            if (StringHelper.isEmpty(saml1String)) {
                boolean standard = metadata.isCustom() || StringHelper.isEmpty(metadata.getUrn())
                        || (!StringHelper.isEmpty(metadata.getUrn())
                                && metadata.getUrn().startsWith("urn:gluu:dir:attribute-def:"));

                saml1String = String.format("urn:%s:dir:attribute-def:%s", standard ? "gluu" : "mace",
                        attributeName);
            }
            attributeSAML1Strings.put(attributeName, saml1String);
            String saml2String = metadata.getSaml2Uri();
            if (StringHelper.isEmpty(saml2String)) {
                saml2String = String.format("urn:oid:%s", attributeTypeDefinition.getOID());
            }
            attributeSAML2Strings.put(attributeName, saml2String);
        }

        attrParams.put("attributes", attributes);
        attrParams.put("attributeSAML1Strings", attributeSAML1Strings);
        attrParams.put("attributeSAML2Strings", attributeSAML2Strings);

        return attrParams;
    }

    private VelocityContext prepareVelocityContext(HashMap<String, Object> trustParams,
            HashMap<String, Object> attrParams, String idpMetadataFolder) {
        //TODO: change for IDP3

        VelocityContext context = new VelocityContext();
        context.put("trustParams", trustParams);
        context.put("attrParams", attrParams);
        context.put("medataFolder", idpMetadataFolder);
        context.put("applianceInum",
                StringHelper.removePunctuation(ApplianceService.instance().getApplianceInum()));
        context.put("orgInum",
                StringHelper.removePunctuation(OrganizationService.instance().getOrganizationInum()));
        context.put("orgSupportEmail", applicationConfiguration.getOrgSupportEmail());

        String idpUrl = applicationConfiguration.getIdpUrl();
        context.put("idpUrl", idpUrl);

        String idpHost = idpUrl.replaceAll(":[0-9]*$", "");
        context.put("idpHost", idpHost);

        String spUrl = applicationConfiguration.getApplianceUrl();
        context.put("spUrl", spUrl);
        String spHost = spUrl.replaceAll(":[0-9]*$", "").replaceAll("^.*?//", "");
        context.put("spHost", spHost);
        String gluuSPInum = ApplianceService.instance().getAppliance().getGluuSPTR();
        String gluuSPEntityId = TrustService.instance().getRelationshipByInum(gluuSPInum).getEntityId();
        context.put("gluuSPEntityId", gluuSPEntityId);
        String regx = "\\s*(=>|,|\\s)\\s*";// white spaces or comma      
        String ldapUrls[] = applicationConfiguration.getIdpLdapServer().split(regx);
        String ldapUrl = "";
        if (ldapUrls != null) {
            for (String ldapServer : ldapUrls) {
                if (ldapUrl.length() > 1)
                    ldapUrl = ldapUrl + " ";
                ldapUrl = ldapUrl + applicationConfiguration.getIdpLdapProtocol() + "://" + ldapServer;

            }
        } else
            ldapUrl = applicationConfiguration.getIdpLdapProtocol() + "://"
                    + applicationConfiguration.getIdpLdapServer();

        context.put("ldapUrl", ldapUrl);
        context.put("bindDN", applicationConfiguration.getIdpBindDn());

        try {
            context.put("ldapPass", StringEncrypter.defaultInstance()
                    .decrypt(applicationConfiguration.getIdpBindPassword(), cryptoConfigurationSalt));
        } catch (EncryptionException e) {
            log.error("Failed to decrypt bindPassword", e);
        }

        context.put("securityKey", applicationConfiguration.getIdpSecurityKey());
        context.put("securityCert", applicationConfiguration.getIdpSecurityCert());
        try {
            context.put("securityKeyPassword", StringEncrypter.defaultInstance()
                    .decrypt(applicationConfiguration.getIdpSecurityKeyPassword(), cryptoConfigurationSalt));
        } catch (EncryptionException e) {
            log.error("Failed to decrypt idp.securityKeyPassword", e);
        }

        context.put("mysqlUrl", applicationConfiguration.getMysqlUrl());
        context.put("mysqlUser", applicationConfiguration.getMysqlUser());

        try {
            String mysqlPassword = applicationConfiguration.getMysqlPassword();
            if (StringHelper.isNotEmpty(mysqlPassword)) {
                mysqlPassword = StringEncrypter.defaultInstance().decrypt(mysqlPassword, cryptoConfigurationSalt);
            }
            context.put("mysqlPass", mysqlPassword);
        } catch (EncryptionException e) {
            log.error("Failed to decrypt mysqlPassword", e);
        }

        return context;
    }

    public String getIdpMetadataFilePath() {
        //TODO: change for IDP3

        if (applicationConfiguration.getShibboleth2IdpRootDir() == null) {
            throw new InvalidConfigurationException(
                    "Failed to find IDP metadata file due to undefined IDP root folder");
        }

        String idpConfFolder = applicationConfiguration.getShibboleth2IdpRootDir() + File.separator
                + SHIB3_IDP_CONF_FOLDER + File.separator;

        File relyingPartyFile = new File(idpConfFolder + SHIB3_IDP_RELYING_PARTY);
        if (!relyingPartyFile.exists()) {
            log.error("Failed to find IDP metadata file name because relaying party file '{0}' doesn't exist",
                    relyingPartyFile.getAbsolutePath());
            return null;
        }

        InputStream is = null;
        InputStreamReader isr = null;
        Document xmlDocument = null;
        try {
            is = FileUtils.openInputStream(relyingPartyFile);
            isr = new InputStreamReader(is, "UTF-8");
            try {
                xmlDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(isr));
            } catch (Exception ex) {
                log.error("Failed to parse relying party file '{0}'", ex, relyingPartyFile.getAbsolutePath());
            }
        } catch (IOException ex) {
            log.error("Failed to read relying party file '{0}'", ex, relyingPartyFile.getAbsolutePath());
        } finally {
            IOUtils.closeQuietly(isr);
            IOUtils.closeQuietly(is);
        }

        if (xmlDocument == null) {
            return null;
        }

        XPathFactory factory = XPathFactory.newInstance();
        XPath xPath = factory.newXPath();

        String filePath = null;
        try {
            filePath = xPath.compile(
                    "/RelyingPartyGroup/MetadataProvider[@id='ShibbolethMetadata']/MetadataProvider[@id='IdPMD']/MetadataResource/@file")
                    .evaluate(xmlDocument);
        } catch (XPathExpressionException ex) {
            log.error("Failed to find IDP metadata file in relaying party file '{0}'", ex,
                    relyingPartyFile.getAbsolutePath());
        }

        if (filePath == null) {
            log.error("Failed to find IDP metadata file in relaying party file '{0}'",
                    relyingPartyFile.getAbsolutePath());
        }

        return filePath;
    }

    public String getSpMetadataFilePath(String spMetaDataFN) {
        //TODO: change for IDP3

        if (applicationConfiguration.getShibboleth2IdpRootDir() == null) {
            throw new InvalidConfigurationException(
                    "Failed to return SP meta-data file due to undefined IDP root folder");
        }

        String idpMetadataFolder = applicationConfiguration.getShibboleth2IdpRootDir() + File.separator
                + SHIB3_IDP_METADATA_FOLDER + File.separator;
        return idpMetadataFolder + spMetaDataFN;
    }

    public String getSpNewMetadataFileName(GluuSAMLTrustRelationship trustRel) {
        //TODO: change for IDP3
        return getSpNewMetadataFileName(trustRel.getInum());
    }

    public String getSpNewMetadataFileName(String inum) {
        //TODO: change for IDP3
        String relationshipInum = StringHelper.removePunctuation(inum);
        return String.format(SHIB3_SP_METADATA_FILE_PATTERN, relationshipInum);
    }

    public String saveSpMetadataFile(String spMetadataFileName, InputStream input) {
        //TODO: change for IDP3
        if (applicationConfiguration.getShibboleth2IdpRootDir() == null) {
            IOUtils.closeQuietly(input);
            String errorMessage = "Failed to save SP meta-data file due to undefined IDP root folder";
            log.error(errorMessage);
            throw new InvalidConfigurationException(errorMessage);
        }

        String idpMetadataFolder = applicationConfiguration.getShibboleth2IdpRootDir() + File.separator
                + SHIB3_IDP_TEMPMETADATA_FOLDER + File.separator;
        String tempFileName = getTempMetadataFilename(idpMetadataFolder, spMetadataFileName);
        File spMetadataFile = new File(idpMetadataFolder + tempFileName);

        FileOutputStream os = null;
        try {
            os = FileUtils.openOutputStream(spMetadataFile);
            IOUtils.copy(input, os);
            os.flush();
        } catch (IOException ex) {
            log.error("Failed to write SP meta-data file '{0}'", ex, spMetadataFile);
            return null;
        } finally {
            IOUtils.closeQuietly(os);
            IOUtils.closeQuietly(input);
        }

        return tempFileName;
    }

    private String getTempMetadataFilename(String idpMetadataFolder, String fileName) {
        //TODO: change for IDP3
        synchronized (getClass()) {
            File possibleTemp = new File(fileName);
            do {
                possibleTemp = new File(idpMetadataFolder + fileName + INumGenerator.generate(2));
            } while (possibleTemp.exists());
            return possibleTemp.getName();
        }
    }

    public String saveSpMetadataFile(String uri, String spMetadataFileName) {
        //TODO: change for IDP3
        if (StringHelper.isEmpty(uri)) {
            return null;
        }
        HTTPFileDownloader.setEasyhttps(new Protocol("https", new EasyCASSLProtocolSocketFactory(), 443));
        String spMetadataFileContent = HTTPFileDownloader.getResource(uri, "application/xml, text/xml", null, null);

        if (StringHelper.isEmpty(spMetadataFileContent)) {
            return null;
        }

        // Save new file
        ByteArrayInputStream is;
        try {
            byte[] spMetadataFileContentBytes = spMetadataFileContent.getBytes("UTF-8");
            is = new ByteArrayInputStream(spMetadataFileContentBytes);
        } catch (UnsupportedEncodingException ex) {
            return null;
        }

        FileUploadWrapper tmpfileWrapper = new FileUploadWrapper();
        tmpfileWrapper.setStream(is);

        return saveSpMetadataFile(spMetadataFileName, tmpfileWrapper.getStream());
    }

    public String generateSpAttributeMapFile(GluuSAMLTrustRelationship trustRelationship) {
        //TODO: change for IDP3
        List<GluuSAMLTrustRelationship> trustRelationships = Arrays.asList(trustRelationship);
        initAttributes(trustRelationships);
        HashMap<String, Object> attrParams = initAttributeParamMap(trustRelationships);

        if (attrParams == null) {
            return null;
        }

        VelocityContext context = prepareVelocityContext(null, attrParams, null);
        String spAttributeMap = templateService.generateConfFile(SHIB3_SP_ATTRIBUTE_MAP, context);

        return spAttributeMap;
    }

    public boolean generateSpMetadataFile(GluuSAMLTrustRelationship trustRelationship, String certificate) {
        //TODO: change for IDP3
        if (applicationConfiguration.getShibboleth2IdpRootDir() == null) {
            throw new InvalidConfigurationException(
                    "Failed to generate SP meta-data file due to undefined IDP root folder");
        }

        String idpMetadataFolder = applicationConfiguration.getShibboleth2IdpRootDir() + File.separator
                + SHIB3_IDP_METADATA_FOLDER + File.separator;

        VelocityContext context = new VelocityContext();
        context.put("certificate", certificate);
        context.put("trustRelationship", trustRelationship);
        context.put("entityId", Util.encodeString(StringHelper.removePunctuation(trustRelationship.getInum())));
        context.put("spHost", trustRelationship.getUrl().replaceFirst("/$", ""));

        // Generate sp-metadata.xml meta-data file
        String spMetadataFileContent = templateService.generateConfFile(SHIB3_IDP_SP_METADATA_FILE, context);
        if (StringHelper.isEmpty(spMetadataFileContent)) {
            return false;
        }

        return templateService.writeConfFile(idpMetadataFolder + trustRelationship.getSpMetaDataFN(),
                spMetadataFileContent);
    }

    public void removeSpMetadataFile(String spMetadataFileName) {
        //TODO: change for IDP3
        if (applicationConfiguration.getShibboleth2IdpRootDir() == null) {
            throw new InvalidConfigurationException(
                    "Failed to remove SP meta-data file due to undefined IDP root folder");
        }

        String idpMetadataFolder = applicationConfiguration.getShibboleth2IdpRootDir() + File.separator
                + SHIB3_IDP_METADATA_FOLDER + File.separator;
        File spMetadataFile = new File(idpMetadataFolder + spMetadataFileName);

        if (spMetadataFile.exists()) {
            spMetadataFile.delete();
        }
    }

    public boolean isCorrectSpMetadataFile(String spMetadataFileName) {
        //TODO: change for IDP3
        if (applicationConfiguration.getShibboleth2IdpRootDir() == null) {
            throw new InvalidConfigurationException(
                    "Failed to check SP meta-data file due to undefined IDP root folder");
        }
        String idpMetadataFolder = applicationConfiguration.getShibboleth2IdpRootDir() + File.separator
                + SHIB3_IDP_METADATA_FOLDER + File.separator;
        File metadataFile = new File(idpMetadataFolder + spMetadataFileName);
        List<String> entityId = SAMLMetadataParser.getSpEntityIdFromMetadataFile(metadataFile);
        return (entityId != null) && !entityId.isEmpty();
    }

    public String getSpAttributeMapFilePath() {
        //TODO: change for IDP3
        String spConfFolder = applicationConfiguration.getShibboleth2SpConfDir() + File.separator;

        return spConfFolder + SHIB3_SP_ATTRIBUTE_MAP;
    }

    public String getSpShibboleth3FilePath() {
        //TODO: change for IDP3
        String spConfFolder = applicationConfiguration.getShibboleth2SpConfDir() + File.separator;

        return spConfFolder + SHIB3_SP_SHIBBOLETH2;
    }

    /**
     * Get shibboleth2ConfService instance
     * 
     * @return Shibboleth2ConfService instance
     */
    public static Shibboleth3ConfService instance() {
        return (Shibboleth3ConfService) Component.getInstance(Shibboleth3ConfService.class);
    }

    public String getSpReadMeResourceName() {
        //TODO: change for IDP3
        return SHIB3_SP_READ_ME;
    }

    public String getSpReadMeWindowsResourceName() {
        //TODO: change for IDP3
        return SHIB3_SP_READ_ME_WINDOWS;
    }

    public String getPublicCertificate(FileUploadWrapper fileWrapper) {
        //TODO: change for IDP3
        if (fileWrapper.getStream() == null) {
            return null;
        }

        List<String> lines = null;
        try {
            lines = (List<String>) IOUtils.readLines(new InputStreamReader(fileWrapper.getStream(), "US-ASCII"));
        } catch (IOException ex) {
            log.error("Failed to read public key file '{0}'", ex, fileWrapper.getFileName());
        } finally {
            IOUtils.closeQuietly(fileWrapper.getStream());
        }

        StringBuilder sb = new StringBuilder();

        boolean keyPart = false;
        for (String line : lines) {
            if (line.startsWith(PUBLIC_CERTIFICATE_END_LINE)) {
                break;
            }
            if (keyPart) {
                if (sb.length() > 0) {
                    sb.append("\n");
                }
                sb.append(line);
            }
            if (line.startsWith(PUBLIC_CERTIFICATE_START_LINE)) {
                keyPart = true;
            }
        }

        if (sb.length() == 0) {
            return null;
        }

        return sb.toString();
    }

    public List<SubversionFile> getConfigurationFilesForSubversion(
            List<GluuSAMLTrustRelationship> trustRelationships) {
        //TODO: change for IDP3
        if (applicationConfiguration.getShibboleth2IdpRootDir() == null) {
            throw new InvalidConfigurationException(
                    "Failed to create SubversionFile file due to undefined IDP root folder");
        }

        String idpConfFolder = applicationConfiguration.getShibboleth2IdpRootDir() + File.separator
                + SHIB3_IDP_CONF_FOLDER + File.separator;
        String idpMetadataFolder = applicationConfiguration.getShibboleth2IdpRootDir() + File.separator
                + SHIB3_IDP_METADATA_FOLDER + File.separator;
        String idpMetadataCredentialsFolder = applicationConfiguration.getShibboleth2IdpRootDir() + File.separator
                + SHIB3_IDP_METADATA_CREDENTIALS_FOLDER + File.separator;
        String spConfFolder = applicationConfiguration.getShibboleth2SpConfDir() + File.separator;

        List<SubversionFile> subversionFiles = new ArrayList<SubversionFile>();
        subversionFiles.add(new SubversionFile(SHIB3_IDP, idpConfFolder + SHIB3_IDP_ATTRIBUTE_RESOLVER_FILE));
        subversionFiles.add(new SubversionFile(SHIB3_IDP, idpConfFolder + SHIB3_IDP_ATTRIBUTE_FILTER_FILE));
        subversionFiles.add(new SubversionFile(SHIB3_IDP, idpConfFolder + SHIB3_IDP_RELYING_PARTY));
        subversionFiles.add(new SubversionFile(SHIB3_SP, spConfFolder + SHIB3_SP_ATTRIBUTE_MAP));
        subversionFiles.add(new SubversionFile(SHIB3_SP, spConfFolder + SHIB3_SP_SHIBBOLETH2));

        for (GluuSAMLTrustRelationship trustRelationship : trustRelationships) {
            if (trustRelationship.getContainerFederation() == null) {
                subversionFiles.add(new SubversionFile(SHIB3_IDP + File.separator + SHIB3_IDP_METADATA_FOLDER,
                        idpMetadataFolder + trustRelationship.getSpMetaDataFN()));
            }
            if (trustRelationship.getMetadataFilters().containsKey("signatureValidation")) {
                subversionFiles
                        .add(new SubversionFile(SHIB3_IDP + File.separator + SHIB3_IDP_METADATA_CREDENTIALS_FOLDER,
                                idpMetadataCredentialsFolder
                                        + StringHelper.removePunctuation(trustRelationship.getInum())));
            }
        }

        return subversionFiles;
    }

    public SubversionFile getConfigurationFileForSubversion(GluuSAMLTrustRelationship trustRelationship) {
        //TODO: change for IDP3
        if (trustRelationship.getSpMetaDataFN() == null) {
            return null;
        }

        if (applicationConfiguration.getShibboleth2IdpRootDir() == null) {
            throw new InvalidConfigurationException(
                    "Failed to create SubversionFile file due to undefined IDP root folder");
        }

        String idpMetadataFolder = applicationConfiguration.getShibboleth2IdpRootDir() + File.separator
                + SHIB3_IDP_METADATA_FOLDER + File.separator;

        return new SubversionFile(SHIB3_IDP + File.separator + SHIB3_IDP_METADATA_FOLDER,
                idpMetadataFolder + trustRelationship.getSpMetaDataFN());
    }

    public boolean isFederationMetadata(String spMetaDataFN) {
        //TODO: change for IDP3
        if (spMetaDataFN == null) {
            return false;
        }
        File spMetaDataFile = new File(getSpMetadataFilePath(spMetaDataFN));
        InputStream is = null;
        InputStreamReader isr = null;
        Document xmlDocument = null;
        try {
            is = FileUtils.openInputStream(spMetaDataFile);
            isr = new InputStreamReader(is, "UTF-8");
            try {
                xmlDocument = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(new InputSource(isr));
            } catch (Exception ex) {
                log.error("Failed to parse metadata file '{0}'", ex, spMetaDataFile.getAbsolutePath());
            }
        } catch (IOException ex) {
            log.error("Failed to read metadata file '{0}'", ex, spMetaDataFile.getAbsolutePath());
        } finally {
            IOUtils.closeQuietly(isr);
            IOUtils.closeQuietly(is);
        }

        if (xmlDocument == null) {
            return false;
        }

        XPathFactory factory = XPathFactory.newInstance();
        XPath xPath = factory.newXPath();

        String federationTag = null;
        try {
            federationTag = xPath.compile("count(/EntitiesDescriptor)").evaluate(xmlDocument);
        } catch (XPathExpressionException ex) {
            log.error("Failed to find IDP metadata file in relaying party file '{0}'", ex,
                    spMetaDataFile.getAbsolutePath());
        }

        return Integer.parseInt(federationTag) > 0;
    }

    public String saveFilterCert(String filterCertFileName, InputStream input) {
        //TODO: change for IDP3
        if (applicationConfiguration.getShibboleth2IdpRootDir() == null) {
            IOUtils.closeQuietly(input);
            throw new InvalidConfigurationException(
                    "Failed to save filter certificate file due to undefined IDP root folder");
        }

        String idpMetadataFolder = applicationConfiguration.getShibboleth2IdpRootDir() + File.separator
                + SHIB3_IDP_METADATA_FOLDER + File.separator + "credentials" + File.separator;
        File filterCertFile = new File(idpMetadataFolder + filterCertFileName);

        FileOutputStream os = null;
        try {
            os = FileUtils.openOutputStream(filterCertFile);
            IOUtils.copy(input, os);
            os.flush();
        } catch (IOException ex) {
            log.error("Failed to write  filter certificate file '{0}'", ex, filterCertFile);
            return null;
        } finally {
            IOUtils.closeQuietly(os);
            IOUtils.closeQuietly(input);
        }

        return filterCertFile.getAbsolutePath();
    }

    public boolean generateIdpConfigurationFiles() {
        //TODO: change for IDP3
        if (applicationConfiguration.getShibboleth2IdpRootDir() == null) {
            throw new InvalidConfigurationException(
                    "Failed to update configuration due to undefined IDP root folder");
        }

        String idpConfFolder = applicationConfiguration.getShibboleth2IdpRootDir() + File.separator
                + SHIB3_IDP_CONF_FOLDER + File.separator;

        // Prepare data for files
        VelocityContext context = new VelocityContext();
        String regx = "\\s*(=>|,|\\s)\\s*";// white spaces or comma      
        String ldapUrls[] = applicationConfiguration.getIdpLdapServer().split(regx);
        String ldapUrl = "";
        if (ldapUrls != null) {
            for (String ldapServer : ldapUrls) {
                if (ldapUrl.length() > 1)
                    ldapUrl = ldapUrl + " ";
                ldapUrl = ldapUrl + applicationConfiguration.getIdpLdapProtocol() + "://" + ldapServer;

            }
        } else
            ldapUrl = applicationConfiguration.getIdpLdapProtocol() + "://"
                    + applicationConfiguration.getIdpLdapServer();
        String host = ldapUrl;
        String base = applicationConfiguration.getBaseDN();
        String serviceUser = applicationConfiguration.getIdpBindDn();
        String serviceCredential = "";
        try {
            serviceCredential = StringEncrypter.defaultInstance()
                    .decrypt(applicationConfiguration.getIdpBindPassword(), cryptoConfigurationSalt);
        } catch (EncryptionException e) {
            log.error("Failed to decrypt bindPassword", e);
        }
        String userField = applicationConfiguration.getIdpUserFields();
        context.put("host", host);
        context.put("base", base);
        context.put("serviceUser", serviceUser);
        context.put("serviceCredential", serviceCredential);
        context.put("userField", userField);

        // Generate login.config
        String loginConfig = templateService.generateConfFile(SHIB3_IDP_LOGIN_CONFIG_FILE, context);

        boolean result = (loginConfig != null);

        // Write login.config
        result &= templateService.writeConfFile(idpConfFolder + SHIB3_IDP_LOGIN_CONFIG_FILE, loginConfig);

        return result;

    }

    public void removeUnusedMetadata() {
        //TODO: change for IDP3
        if (applicationConfiguration.getShibboleth2IdpRootDir() == null) {
            throw new InvalidConfigurationException(
                    "Failed to update configuration due to undefined IDP root folder");
        }
        File metadataDir = new File(
                applicationConfiguration.getShibboleth2IdpRootDir() + File.separator + SHIB3_IDP_METADATA_FOLDER);

        if (metadataDir.exists()) {
            ArrayList<SubversionFile> obsoleteMetadata = new ArrayList<SubversionFile>();

            for (File metadata : metadataDir.listFiles(new FileFilter() {
                public boolean accept(File pathname) {
                    return pathname.isFile();
                }
            })) {
                if (trustRelationExists(metadata.getName())) {
                    continue;
                }
                obsoleteMetadata.add(new SubversionFile(SHIB3_IDP + File.separator + SHIB3_IDP_METADATA_FOLDER,
                        metadata.getAbsolutePath()));
            }
            SubversionService.instance().commitShibboleth2ConfigurationFiles(
                    OrganizationService.instance().getOrganization(), new ArrayList<SubversionFile>(),
                    obsoleteMetadata, "Removed Metadata files that are no longer used");
            for (SubversionFile file : obsoleteMetadata) {
                new File(file.getLocalFile()).delete();
            }
        }

    }

    private boolean trustRelationExists(String metadataName) {
        //TODO: change for IDP3
        if (metadataName.equals(
                StringHelper.removePunctuation(applicationConfiguration.getOrgInum()) + "-idp-metadata.xml")) {
            return true;
        }
        for (GluuSAMLTrustRelationship trust : TrustService.instance().getAllTrustRelationships()) {
            if (metadataName.equals(trust.getSpMetaDataFN())) {
                return true;
            }
        }
        return false;
    }

    public void removeUnusedCredentials() {
        //TODO: change for IDP3
        if (applicationConfiguration.getShibboleth2IdpRootDir() == null) {
            throw new InvalidConfigurationException(
                    "Failed to update configuration due to undefined IDP root folder");
        }
        File credentialsDir = new File(applicationConfiguration.getShibboleth2IdpRootDir() + File.separator
                + SHIB3_IDP_METADATA_CREDENTIALS_FOLDER);
        if (credentialsDir.exists()) {
            ArrayList<SubversionFile> obsoleteMetadata = new ArrayList<SubversionFile>();
            for (File credential : credentialsDir.listFiles(new FileFilter() {
                public boolean accept(File pathname) {
                    return pathname.isFile();
                }
            })) {
                if (filterExists(credential.getName()) || profileCofigurationExists(credential.getName())) {
                    continue;
                }
                obsoleteMetadata
                        .add(new SubversionFile(SHIB3_IDP + File.separator + SHIB3_IDP_METADATA_CREDENTIALS_FOLDER,
                                credential.getAbsolutePath()));
            }
            SubversionService.instance().commitShibboleth2ConfigurationFiles(
                    OrganizationService.instance().getOrganization(), new ArrayList<SubversionFile>(),
                    obsoleteMetadata, "Removed Credentials files that are no longer used");
            for (SubversionFile file : obsoleteMetadata) {
                new File(file.getLocalFile()).delete();
            }
        }
    }

    private boolean profileCofigurationExists(String credentialName) {
        //TODO: change for IDP3
        for (GluuSAMLTrustRelationship trust : TrustService.instance().getAllTrustRelationships()) {
            if (credentialName.contains(StringHelper.removePunctuation(trust.getInum()))
                    && !credentialName.equals(StringHelper.removePunctuation(trust.getInum()))) {
                try {
                    ProfileConfigurationService.instance().parseProfileConfigurations(trust);
                } catch (Exception e) {
                    return false;
                }

                ProfileConfiguration profileConfiguration = trust.getProfileConfigurations()
                        .get(credentialName.replace(StringHelper.removePunctuation(trust.getInum()), ""));
                if (profileConfiguration != null
                        && credentialName.equals(profileConfiguration.getProfileConfigurationCertFileName())) {
                    return true;
                }
            }
        }
        return false;
    }

    private boolean filterExists(String credentialName) {
        //TODO: change for IDP3
        for (GluuSAMLTrustRelationship trust : TrustService.instance().getAllTrustRelationships()) {
            if (credentialName.equals(StringHelper.removePunctuation(trust.getInum()))) {
                try {
                    FilterService.instance().parseFilters(trust);
                } catch (Exception e) {
                    return false;
                }
                if (trust.getMetadataFilters().get("signatureValidation") != null) {
                    return true;
                }
            }
        }
        return false;
    }

    public String saveProfileConfigurationCert(String profileConfigurationCertFileName, InputStream stream) {
        //TODO: change for IDP3
        if (applicationConfiguration.getShibboleth2IdpRootDir() == null) {
            IOUtils.closeQuietly(stream);
            throw new InvalidConfigurationException(
                    "Failed to save Profile Configuration file due to undefined IDP root folder");
        }

        String idpMetadataFolder = applicationConfiguration.getShibboleth2IdpRootDir() + File.separator
                + SHIB3_IDP_METADATA_FOLDER + File.separator + "credentials" + File.separator;
        File filterCertFile = new File(idpMetadataFolder + profileConfigurationCertFileName);

        FileOutputStream os = null;
        try {
            os = FileUtils.openOutputStream(filterCertFile);
            IOUtils.copy(stream, os);
            os.flush();
        } catch (IOException ex) {
            log.error("Failed to write  Profile Configuration  certificate file '{0}'", ex, filterCertFile);
            return null;
        } finally {
            IOUtils.closeQuietly(os);
            IOUtils.closeQuietly(stream);
        }

        return filterCertFile.getAbsolutePath();

    }

    public boolean isCorrectMetadataFile(String spMetaDataFN) {
        //TODO: change for IDP3
        if (applicationConfiguration.getShibboleth2FederationRootDir() == null) {
            throw new InvalidConfigurationException(
                    "Failed to check meta-data file due to undefined federation root folder");
        }
        String metadataFolder = applicationConfiguration.getShibboleth2FederationRootDir() + File.separator
                + SHIB3_IDP_METADATA_FOLDER + File.separator;
        File metadataFile = new File(metadataFolder + spMetaDataFN);
        List<String> entityId = SAMLMetadataParser.getEntityIdFromMetadataFile(metadataFile);
        return (entityId != null) && !entityId.isEmpty();
    }

    public void removeMetadataFile(String spMetaDataFN) {
        //TODO: change for IDP3
        if (applicationConfiguration.getShibboleth2FederationRootDir() == null) {
            throw new InvalidConfigurationException(
                    "Failed to remove meta-data file due to undefined federation root folder");
        }

        String metadataFolder = applicationConfiguration.getShibboleth2FederationRootDir() + File.separator
                + SHIB3_IDP_METADATA_FOLDER + File.separator;
        File spMetadataFile = new File(metadataFolder + spMetaDataFN);

        if (spMetadataFile.exists()) {
            spMetadataFile.delete();
        }
    }

    public String getMetadataFilePath(String metadataFileName) {
        //TODO: change for IDP3
        if (applicationConfiguration.getShibboleth2FederationRootDir() == null) {
            throw new InvalidConfigurationException(
                    "Failed to return meta-data file due to undefined federation root folder");
        }

        String metadataFolderName = applicationConfiguration.getShibboleth2FederationRootDir() + File.separator
                + SHIB3_IDP_METADATA_FOLDER + File.separator;
        File metadataFolder = new File(metadataFolderName);
        if (!metadataFolder.exists()) {
            metadataFolder.mkdirs();
        }
        return metadataFolderName + metadataFileName;
    }

    public String getNewMetadataFileName(GluuSAMLFederationProposal federationProposal,
            List<GluuSAMLFederationProposal> allFederationProposals) {
        //TODO: change for IDP3
        String relationshipInum = StringHelper.removePunctuation(federationProposal.getInum());

        return String.format(SHIB3_METADATA_FILE_PATTERN, relationshipInum);
    }

    public boolean saveMetadataFile(String metadataFileName, InputStream stream) {
        //TODO: change for IDP3
        if (applicationConfiguration.getShibboleth2FederationRootDir() == null) {
            IOUtils.closeQuietly(stream);
            throw new InvalidConfigurationException(
                    "Failed to save meta-data file due to undefined federation root folder");
        }

        String idpMetadataFolderName = applicationConfiguration.getShibboleth2FederationRootDir() + File.separator
                + SHIB3_IDP_METADATA_FOLDER + File.separator;
        File idpMetadataFolder = new File(idpMetadataFolderName);
        if (!idpMetadataFolder.exists()) {
            idpMetadataFolder.mkdirs();
        }
        File spMetadataFile = new File(idpMetadataFolderName + metadataFileName);

        FileOutputStream os = null;
        try {
            os = FileUtils.openOutputStream(spMetadataFile);
            IOUtils.copy(stream, os);
            os.flush();
        } catch (IOException ex) {
            log.error("Failed to write meta-data file '{0}'", ex, spMetadataFile);
            return false;
        } finally {
            IOUtils.closeQuietly(os);
            IOUtils.closeQuietly(stream);
        }

        return true;
    }

    public boolean saveMetadataFile(String spMetaDataURL, String metadataFileName) {
        //TODO: change for IDP3
        if (StringHelper.isEmpty(spMetaDataURL)) {
            return false;
        }

        String metadataFileContent = HTTPFileDownloader.getResource(spMetaDataURL, "application/xml, text/xml",
                null, null);

        if (StringHelper.isEmpty(metadataFileContent)) {
            return false;
        }

        // Save new file
        ByteArrayInputStream is;
        try {
            byte[] metadataFileContentBytes = metadataFileContent.getBytes("UTF-8");
            is = new ByteArrayInputStream(metadataFileContentBytes);
        } catch (UnsupportedEncodingException ex) {
            return false;
        }

        FileUploadWrapper tmpfileWrapper = new FileUploadWrapper();
        tmpfileWrapper.setStream(is);

        return saveMetadataFile(metadataFileName, tmpfileWrapper.getStream());
    }

    /**
     * Generate metadata files needed for appliance operations: gluuSP metadata
     * and idp metadata.
     */
    public boolean generateMetadataFiles(GluuSAMLTrustRelationship gluuSP) {
        //TODO: change for IDP3
        if (applicationConfiguration.getShibboleth2IdpRootDir() == null) {
            throw new InvalidConfigurationException(
                    "Failed to update configuration due to undefined IDP root folder");
        }

        String idpMetadataFolder = applicationConfiguration.getShibboleth2IdpRootDir() + File.separator
                + SHIB3_IDP_METADATA_FOLDER + File.separator;

        // Prepare data for files
        VelocityContext context = new VelocityContext();
        String idpHost = applicationConfiguration.getIdpUrl();

        context.put("idpHost", idpHost);
        String domain = idpHost.replaceAll(":[0-9]*$", "").replaceAll("^.*?//", "");
        context.put("domain", domain);
        try {
            String idpCertificate = FileUtils
                    .readFileToString(new File(applicationConfiguration.getIdpSecurityCert()))
                    .replaceAll("-{5}.*?-{5}", "");
            context.put("idpCertificate", idpCertificate);

        } catch (IOException e) {
            log.error("Unable to get idp certificate from " + applicationConfiguration.getIdpSecurityCert(), e);
            return false;
        }

        try {
            String spCertificate = FileUtils.readFileToString(new File(applicationConfiguration.getGluuSpCert()))
                    .replaceAll("-{5}.*?-{5}", "");
            if (gluuSP.getUrl() == null || "".equals(gluuSP.getUrl())) {
                gluuSP.setUrl(applicationConfiguration.getApplianceUrl());
            }
            generateSpMetadataFile(gluuSP, spCertificate);
        } catch (IOException e) {
            log.error("Unable to get sp certificate from " + applicationConfiguration.getGluuSpCert(), e);
            return false;
        }

        // Generate login.config
        String idpMetadata = templateService.generateConfFile(SHIB3_IDP_IDP_METADATA_FILE, context);

        boolean result = (idpMetadata != null);
        String idpMetadataName = String.format(SHIB3_IDP_METADATA_FILE_PATTERN,
                StringHelper.removePunctuation(OrganizationService.instance().getOrganizationInum()));
        // Write login.config
        result &= templateService.writeConfFile(idpMetadataFolder + File.separator + idpMetadataName, idpMetadata);

        return result;

    }

    /**
     * @param stream
     * @throws IOException
     * @throws SAXException
     * @throws ParserConfigurationException
     * @return GluuErrorHandler
     */
    public static GluuErrorHandler validateMetadata(InputStream stream)
            throws ParserConfigurationException, SAXException, IOException {
        //TODO: change for IDP3
        String schemaDir = OxTrustConfiguration.DIR + "shibboleth2" + File.separator + "idp" + File.separator
                + "schema" + File.separator;
        Schema schema = SchemaBuilder.buildSchema(SchemaLanguage.XML, schemaDir);

        return XMLValidator.validateMetadata(stream, schema);
    }
}