package org.apereo.cas.support.saml.services.idp.metadata.cache.resolver;

import org.apache.commons.io.FileUtils;
import org.apereo.cas.configuration.model.support.saml.idp.SamlIdPProperties;
import org.apereo.cas.support.saml.OpenSamlConfigBean;
import org.apereo.cas.support.saml.services.SamlRegisteredService;
import org.apereo.cas.util.CollectionUtils;
import org.apereo.cas.util.ResourceUtils;
import org.apereo.cas.util.http.HttpClient;
import org.opensaml.saml.metadata.resolver.MetadataResolver;
import org.opensaml.saml.metadata.resolver.impl.FileBackedHTTPMetadataResolver;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.core.io.AbstractResource;
import org.springframework.core.io.FileSystemResource;
import org.springframework.core.io.UrlResource;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;

/**
 * This is {@link UrlResourceMetadataResolver}.
 *
 * @author Misagh Moayyed
 * @since 5.2.0
 */
public class UrlResourceMetadataResolver extends BaseSamlRegisteredServiceMetadataResolver {
    private static final Logger LOGGER = LoggerFactory.getLogger(DynamicMetadataResolver.class);

    private final HttpClient httpClient;
    
    public UrlResourceMetadataResolver(final SamlIdPProperties samlIdPProperties,
                                       final OpenSamlConfigBean configBean,
                                       final HttpClient httpClient) {
        super(samlIdPProperties, configBean);
        this.httpClient = httpClient;
    }

    @Override
    public Collection<MetadataResolver> resolve(final SamlRegisteredService service) {
        try {

            final String metadataLocation = service.getMetadataLocation();
            LOGGER.info("Loading SAML metadata from [{}]", metadataLocation);
            final AbstractResource metadataResource = ResourceUtils.getResourceFrom(metadataLocation);
            
            final SamlIdPProperties.Metadata md = samlIdPProperties.getMetadata();
            final File backupDirectory = new File(md.getLocation().getFile(), "metadata-backups");
            final File backupFile = new File(backupDirectory, metadataResource.getFilename());

            LOGGER.debug("Metadata backup directory is designated to be [{}]", backupDirectory.getCanonicalPath());
            FileUtils.forceMkdir(backupDirectory);

            final String canonicalPath = backupFile.getCanonicalPath();
            LOGGER.debug("Metadata backup file will be at [{}]", canonicalPath);
            FileUtils.forceMkdirParent(backupFile);

            final FileBackedHTTPMetadataResolver metadataProvider = new FileBackedHTTPMetadataResolver(
                    this.httpClient.getWrappedHttpClient(), metadataResource.getURL().toExternalForm(),
                    canonicalPath);
            buildSingleMetadataResolver(metadataProvider, service);
            return CollectionUtils.wrap(metadataProvider);
        } catch (final Exception e) {
            LOGGER.error(e.getMessage(), e);
        }
        return new ArrayList<>();
    }

    @Override
    public boolean supports(final SamlRegisteredService service) {
        try {
            final String metadataLocation = service.getMetadataLocation();
            final AbstractResource metadataResource = ResourceUtils.getResourceFrom(metadataLocation);
            return metadataResource instanceof UrlResource;
        } catch (final Exception e) {
            LOGGER.error(e.getMessage(), e);
        }
        return false;
    }
}

@@ -186,16 +186,66 @@
 erties;%0A
+import org.apereo.cas.services.RegisteredService;%0A
 import o
@@ -291,16 +291,16 @@
 igBean;%0A
-
 import o
@@ -743,63 +743,8 @@
 ce;%0A
-import org.springframework.core.io.FileSystemResource;%0A
 impo
@@ -809,16 +809,44 @@
 o.File;%0A
+import java.io.IOException;%0A
 import j
@@ -893,16 +893,39 @@
 lection;
+%0Aimport java.util.UUID;
 %0A%0A/**%0A *
@@ -1982,436 +1982,76 @@
 nal 
-SamlIdPProperties.Metadata md = samlIdPProperties.getMetadata();%0A            final File backupDirectory = new File(md.getLocation().getFile(), %22m
+File backupFile = getM
 etadata
--b
+B
 ackup
-s%22);%0A            final File backupFile = new File(backupDirectory, metadataResource.getFilename());%0A%0A            LOGGER.debug(%22Metadata backup directory is designated to be %5B%7B%7D%5D%22, backupDirectory.getCanonicalPath());%0A            FileUtils.forceMkdir(backupDirectory
+File(metadataResource, service
 );%0A
-%0A
     
@@ -2708,32 +2708,32 @@
 , e);%0A        %7D%0A
-
         return n
@@ -2749,32 +2749,1139 @@
 ist%3C%3E();%0A    %7D%0A%0A
+    private File getMetadataBackupFile(final AbstractResource metadataResource,%0A                                       final RegisteredService service) throws IOException %7B%0A        final SamlIdPProperties.Metadata md = samlIdPProperties.getMetadata();%0A        final File backupDirectory = new File(md.getLocation().getFile(), %22metadata-backups%22);%0A        LOGGER.debug(%22Metadata backup directory is at %5B%7B%7D%5D%22, backupDirectory.getCanonicalPath());%0A        %0A        final String metadataFileName = service.getName().concat(%22-%22).concat(UUID.randomUUID().toString()).concat(metadataResource.getFilename());%0A        final File backupFile = new File(backupDirectory, metadataFileName);%0A        if (backupFile.exists()) %7B%0A            LOGGER.warn(%22Metadata file designated for service %5B%7B%7D%5D already exists at path %5B%7B%7D%5D.%22, service.getName(), backupFile.getCanonicalPath());%0A        %7D else %7B%0A            LOGGER.debug(%22Metadata to fetch for service %5B%7B%7D%5D will be placed at %5B%7B%7D%5D%22, service.getName(), backupFile.getCanonicalPath());%0A        %7D%0A        FileUtils.forceMkdir(backupDirectory);%0A        return backupFile;%0A    %7D%0A%0A
     @Override%0A  

Remove chance of metadata collission