public Collection<Path> backup() throws IOException
    {
        // Create a collection that holds all of the certificate stores.
        final Collection<CertificateStore> allStores = new ArrayList<>();
        allStores.addAll( identityStores.values() );
        allStores.addAll( trustStores.values() );

        // Extract the set of unique file/backup-directory combinations. This prevents Openfire from creating duplicate backup files.
        final Set<CertificateStore> unique = allStores.stream().filter(
            CollectionUtils.distinctByKey(
                store -> store.getConfiguration().getFile().getAbsolutePath() + "|" + store.configuration.backupDirectory.getAbsolutePath() ) )
            .collect( Collectors.toSet() );

        // Trigger a backup for each of the unique combinations, and record the unique backup locations
        final Collection<Path> backups = unique.stream()
            .map( CertificateStore::backup )
            .filter( Objects::nonNull )
            .distinct()
            .sorted()
            .collect( Collectors.toList() );

        // If the number of backups is smaller than the number of unique file/backup-directory combinations, something went wrong!
        if ( unique.size() != backups.size() ) {
            throw new IOException( "Unable to create (all) backups!" );
        }

        return backups;
    }
Creates a backup of all files that back any of the certificate stores.

Each certificate store can be configured to use a distinct file, as well as use a distinct backup location.
In practise, there will be a lot of overlap. This implementation creates a backup (by copying the file) for
each unique file/backup-location combination in the collection of all certificate stores.
@return the paths the store was backed up to
@throws IOException if the store could not be backed up
xmppserver/src/main/java/org/jivesoftware/openfire/keystore/CertificateStoreManager.java