org.geoserver.backuprestore.tasklet.CatalogBackupRestoreTasklet.java Source code

Java tutorial

Introduction

Here is the source code for org.geoserver.backuprestore.tasklet.CatalogBackupRestoreTasklet.java

Source

/* (c) 2016 Open Source Geospatial Foundation - all rights reserved
 * This code is licensed under the GPL 2.0 license, available at the root
 * application directory.
 */
package org.geoserver.backuprestore.tasklet;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.logging.Level;

import org.apache.commons.io.FileUtils;
import org.geoserver.backuprestore.Backup;
import org.geoserver.backuprestore.utils.BackupUtils;
import org.geoserver.catalog.CoverageInfo;
import org.geoserver.catalog.CoverageStoreInfo;
import org.geoserver.catalog.DataStoreInfo;
import org.geoserver.catalog.FeatureTypeInfo;
import org.geoserver.catalog.LayerGroupInfo;
import org.geoserver.catalog.LayerInfo;
import org.geoserver.catalog.NamespaceInfo;
import org.geoserver.catalog.StyleInfo;
import org.geoserver.catalog.ValidationResult;
import org.geoserver.catalog.WorkspaceInfo;
import org.geoserver.config.GeoServer;
import org.geoserver.config.GeoServerDataDirectory;
import org.geoserver.config.GeoServerInfo;
import org.geoserver.config.GeoServerPluginConfigurator;
import org.geoserver.config.GeoServerPropertyConfigurer;
import org.geoserver.config.LoggingInfo;
import org.geoserver.config.ServiceInfo;
import org.geoserver.config.SettingsInfo;
import org.geoserver.config.util.XStreamPersisterFactory;
import org.geoserver.gwc.config.GWCConfig;
import org.geoserver.gwc.config.GWCConfigPersister;
import org.geoserver.gwc.config.GWCInitializer;
import org.geoserver.gwc.config.GeoserverXMLResourceProvider;
import org.geoserver.gwc.layer.DefaultTileLayerCatalog;
import org.geoserver.gwc.layer.GeoServerTileLayerInfo;
import org.geoserver.gwc.layer.TileLayerCatalog;
import org.geoserver.platform.GeoServerExtensions;
import org.geoserver.platform.GeoServerResourceLoader;
import org.geoserver.platform.resource.Files;
import org.geoserver.platform.resource.Paths;
import org.geoserver.platform.resource.Resource;
import org.geoserver.platform.resource.ResourceStore;
import org.geoserver.platform.resource.Resources;
import org.geoserver.util.Filter;
import org.geowebcache.config.XMLConfiguration;
import org.springframework.batch.core.JobExecution;
import org.springframework.batch.core.StepContribution;
import org.springframework.batch.core.StepExecution;
import org.springframework.batch.core.UnexpectedJobExecutionException;
import org.springframework.batch.core.scope.context.ChunkContext;
import org.springframework.batch.repeat.RepeatStatus;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.util.Assert;

import com.google.common.collect.BiMap;
import com.google.common.collect.HashBiMap;
import com.google.common.collect.Maps;

/**
 * Concrete implementation of the {@link AbstractCatalogBackupRestoreTasklet}.
 * <br>
 * Actually takes care of dumping/restoring everything is not a {@link ResourceInfo},
 * like the GeoServer settings, logging and global/local (workspaces) infos.
 * 
 * @author Alessio Fabiani, GeoSolutions
 *
 */
public class CatalogBackupRestoreTasklet extends AbstractCatalogBackupRestoreTasklet {

    public CatalogBackupRestoreTasklet(Backup backupFacade, XStreamPersisterFactory xStreamPersisterFactory) {
        super(backupFacade, xStreamPersisterFactory);
    }

    @Override
    protected void initialize(StepExecution stepExecution) {

    }

    @Override
    RepeatStatus doExecute(StepContribution contribution, ChunkContext chunkContext, JobExecution jobExecution)
            throws Exception {
        final GeoServer geoserver = backupFacade.getGeoServer();
        final GeoServerDataDirectory dd = backupFacade.getGeoServerDataDirectory();
        final ResourceStore resourceStore = dd.getResourceStore();

        try {
            if (!isNew()) {
                doBackup(jobExecution, geoserver, dd, resourceStore);
            } else {
                doRestore(jobExecution, geoserver, dd);
            }
        } catch (Exception e) {
            logValidationExceptions((ValidationResult) null, new UnexpectedJobExecutionException(
                    "Exception occurred while storing GeoServer globals and services settings!", e));
        }

        return RepeatStatus.FINISHED;
    }

    /**
     * Perform Backup
     * 
     * @param jobExecution
     * @param geoserver
     * @param dd
     * @param resourceStore
     * @throws Exception
     * @throws IOException
     */
    private void doBackup(JobExecution jobExecution, final GeoServer geoserver, final GeoServerDataDirectory dd,
            final ResourceStore resourceStore) throws Exception {
        try {
            final String outputFolderURL = jobExecution.getJobParameters().getString(Backup.PARAM_OUTPUT_FILE_PATH);
            Resource targetBackupFolder = Resources.fromURL(outputFolderURL);

            // Store GeoServer Global Info
            doWrite(geoserver.getGlobal(), targetBackupFolder, "global.xml");

            // Store GeoServer Global Settings
            doWrite(geoserver.getSettings(), targetBackupFolder, "settings.xml");

            // Store GeoServer Global Logging Settings
            doWrite(geoserver.getLogging(), targetBackupFolder, "logging.xml");

            // Store GeoServer Global Services
            for (ServiceInfo service : geoserver.getServices()) {
                // Local Services will be saved later on ...
                if (service.getWorkspace() == null) {
                    doWrite(service, targetBackupFolder, "services");
                }
            }

            // Save Workspace specific settings
            Resource targetWorkspacesFolder = BackupUtils.dir(targetBackupFolder, "workspaces");

            // Store Default Workspace
            if (filteredWorkspace(getCatalog().getDefaultWorkspace())) {
                doWrite(getCatalog().getDefaultNamespace(), targetWorkspacesFolder, "defaultnamespace.xml");
                doWrite(getCatalog().getDefaultWorkspace(), targetWorkspacesFolder, "default.xml");
            }

            // Store Workspace Specific Settings and Services
            for (WorkspaceInfo ws : getCatalog().getWorkspaces()) {
                if (filteredWorkspace(ws)) {
                    if (geoserver.getSettings(ws) != null) {
                        doWrite(geoserver.getSettings(ws), BackupUtils.dir(targetWorkspacesFolder, ws.getName()),
                                "settings.xml");
                    }

                    if (geoserver.getServices(ws) != null) {
                        for (ServiceInfo service : geoserver.getServices(ws)) {
                            doWrite(service, targetWorkspacesFolder, ws.getName());
                        }
                    }

                    // Backup other configuration bits, like images, palettes, user projections and so on...
                    GeoServerDataDirectory wsDd = new GeoServerDataDirectory(
                            dd.get(Paths.path("workspaces", ws.getName())).dir());
                    backupRestoreAdditionalResources(wsDd.getResourceStore(),
                            targetWorkspacesFolder.get(ws.getName()));

                    // Backup Style SLDs
                    for (StyleInfo sty : getCatalog().getStylesByWorkspace(ws)) {
                        Resource styResource = wsDd.get(Paths.path("styles", sty.getFilename()));
                        if (Resources.exists(styResource)) {
                            Resources.copy(styResource.file(),
                                    BackupUtils.dir(targetWorkspacesFolder.get(ws.getName()), "styles"));
                        }
                    }
                }
            }

            // Backup GeoServer Plugins
            final GeoServerResourceLoader targetGeoServerResourceLoader = new GeoServerResourceLoader(
                    targetBackupFolder.dir());
            for (GeoServerPluginConfigurator pluginConfig : GeoServerExtensions
                    .extensions(GeoServerPluginConfigurator.class)) {
                // On restore invoke 'pluginConfig.loadConfiguration(resourceLoader);' after having replaced the config files.
                pluginConfig.saveConfiguration(targetGeoServerResourceLoader);
            }

            for (GeoServerPropertyConfigurer props : GeoServerExtensions
                    .extensions(GeoServerPropertyConfigurer.class)) {
                // On restore invoke 'props.reload();' after having replaced the properties files.
                Resource configFile = props.getConfigFile();

                if (configFile != null && Resources.exists(configFile)) {
                    Resource targetDir = Files.asResource(targetGeoServerResourceLoader.findOrCreateDirectory(
                            Paths.convert(dd.getResourceLoader().getBaseDirectory(), configFile.parent().dir())));

                    Resources.copy(configFile.file(), targetDir);
                }
            }

            // Backup other configuration bits, like images, palettes, user projections and so on...
            backupRestoreAdditionalResources(resourceStore, targetBackupFolder);

            // Backup GWC Configuration bits
            try {
                if (GeoServerExtensions.bean("gwcGeoServervConfigPersister") != null) {
                    backupGWCSettings(targetBackupFolder);
                }
            } catch (NoSuchBeanDefinitionException e) {
                LOGGER.log(Level.WARNING, "Skipped GWC GeoServer Config Persister: ", e);
            }
        } catch (Exception e) {
            logValidationExceptions((ValidationResult) null, new UnexpectedJobExecutionException(
                    "Exception occurred while storing GeoServer globals and services settings!", e));
        }
    }

    /**
     * @param ws
     * @return
     */
    private boolean filteredWorkspace(WorkspaceInfo ws) {
        return getFilter() == null || (getFilter() != null && getFilter().evaluate(ws));
    }

    /**
     * @param jobExecution
     * @param geoserver
     * @param dd
     * @throws Exception
     * @throws IOException
     * @throws UnexpectedJobExecutionException
     */
    @SuppressWarnings("unused")
    private void doRestore(JobExecution jobExecution, final GeoServer geoserver, final GeoServerDataDirectory dd)
            throws Exception {
        final String inputFolderURL = jobExecution.getJobParameters().getString(Backup.PARAM_INPUT_FILE_PATH);
        Resource sourceRestoreFolder = Resources.fromURL(inputFolderURL);
        Resource sourceWorkspacesFolder = null;

        // Try first to load all the settings available into the source restore folder
        GeoServerInfo newGeoServerInfo = null;
        SettingsInfo newSettings = null;
        LoggingInfo newLoggingInfo = null;
        try {
            newGeoServerInfo = (GeoServerInfo) doRead(sourceRestoreFolder, "global.xml");
            newSettings = (SettingsInfo) doRead(sourceRestoreFolder, "settings.xml");
            newLoggingInfo = (LoggingInfo) doRead(sourceRestoreFolder, "logging.xml");
        } catch (Exception e) {
            logValidationExceptions((ValidationResult) null, new UnexpectedJobExecutionException(
                    "Exception occurred while storing GeoServer globals and services settings!", e));
        }

        // Save Workspace specific settings
        try {
            sourceWorkspacesFolder = BackupUtils.dir(sourceRestoreFolder, "workspaces");

            // Set Default Namespace and Workspace
            if (Resources.exists(sourceWorkspacesFolder.get("default.xml"))) {
                NamespaceInfo newDefaultNamespace = (NamespaceInfo) doRead(sourceWorkspacesFolder,
                        "defaultnamespace.xml");
                WorkspaceInfo newDefaultWorkspace = (WorkspaceInfo) doRead(sourceWorkspacesFolder, "default.xml");
                getCatalog().setDefaultNamespace(newDefaultNamespace);
                getCatalog().setDefaultWorkspace(newDefaultWorkspace);
            }
        } catch (Exception e) {
            logValidationExceptions((ValidationResult) null, new UnexpectedJobExecutionException(
                    "Exception occurred while storing GeoServer globals and services settings!", e));
        }

        // RESTORE
        // TODO: Save old settings
        /*
         * GeoServerInfo oldGeoServerInfo = geoserver.getGlobal(); SettingsInfo oldSettings = geoserver.getSettings(); LoggingInfo oldLoggingInfo =
         * geoserver.getLogging(); WorkspaceInfo oldDefaultWorkspace = geoserver.getCatalog().getDefaultWorkspace(); NamespaceInfo oldDefaultNamespace
         * = geoserver.getCatalog().getDefaultNamespace();
         */

        // Do this *ONLY* when DRY-RUN-MODE == OFF
        if (!isDryRun()) {
            try {
                hardRestore(geoserver, dd, sourceRestoreFolder, sourceWorkspacesFolder, newGeoServerInfo,
                        newLoggingInfo);
            } catch (Exception e) {
                logValidationExceptions((ValidationResult) null, new UnexpectedJobExecutionException(
                        "Exception occurred while storing GeoServer globals and services settings!", e));
            } finally {
                /*
                 * TODO: - Handle Revert ??
                 */
            }
        } else {
            // DRY-RUN-MODE ON: Try to check backup files consistency as much as possible
            try {
                // Temporary GeoServer Data Dir just for testing
                GeoServerDataDirectory td = new GeoServerDataDirectory(BackupUtils.tmpDir().dir());
                softRestore(geoserver, td, sourceRestoreFolder, sourceWorkspacesFolder, newGeoServerInfo,
                        newLoggingInfo);
            } catch (Exception e) {
                logValidationExceptions((ValidationResult) null, new UnexpectedJobExecutionException(
                        "Exception occurred while storing GeoServer globals and services settings!", e));
            } finally {
            }
        }
    }

    /**
     * @param geoserver
     * @param dd
     * @param sourceRestoreFolder
     * @param newGeoServerInfo
     * @param newLoggingInfo
     * @param sourceWorkspacesFolder
     * @throws IOException
     * @throws Exception
     * @throws IllegalArgumentException
     */
    private void hardRestore(final GeoServer geoserver, final GeoServerDataDirectory dd,
            Resource sourceRestoreFolder, Resource sourceWorkspacesFolder, GeoServerInfo newGeoServerInfo,
            LoggingInfo newLoggingInfo) throws IOException, Exception, IllegalArgumentException {
        // TODO: add option 'cleanUpGeoServerDataDir'
        // TODO: purge/preserve GEOSERVER_DATA_DIR
        geoserver.getCatalog().getResourcePool().dispose();
        geoserver.getCatalog().dispose();
        geoserver.dispose();

        // Restore GeoServer Global Info
        Files.delete(dd.get("global.xml").file());
        doWrite(newGeoServerInfo, dd.get(Paths.BASE), "global.xml");
        geoserver.setGlobal(newGeoServerInfo);

        // Restore GeoServer Global Logging Settings
        Files.delete(dd.get("logging.xml").file());
        doWrite(newLoggingInfo, dd.get(Paths.BASE), "logging.xml");
        geoserver.setLogging(newLoggingInfo);

        restoreGlobalServices(sourceRestoreFolder, dd);

        // Restore Workspaces
        // - Prepare folder
        Resource workspaces = dd.get("workspaces");
        // - TODO: if purge
        Files.delete(workspaces.dir());
        workspaces = BackupUtils.dir(dd.get(Paths.BASE), "workspaces");

        restoreWorkSpacesAndLayers(workspaces);

        // Restore GeoServer Settings
        // - GeoServer Catalog Alignment
        geoserver.reload(getCatalog());

        // Restore Styles
        // - Prepare folder
        Resource styles = dd.get("styles");
        // - TODO: if purge
        Files.delete(styles.dir());
        styles = BackupUtils.dir(dd.get(Paths.BASE), "styles");

        restoreGlobalStyles(sourceRestoreFolder, styles);

        // Restore LayerGroups
        // - Prepare folder
        Resource layerGroups = dd.get("layergroups");
        // - TODO: if purge
        Files.delete(layerGroups.dir());
        layerGroups = BackupUtils.dir(dd.get(Paths.BASE), "layergroups");

        restoreGlobalLayerGroups(layerGroups);

        // Restore Workspace Specific Settings and Services
        restoreLocalWorkspaceSettingsAndServices(geoserver, sourceRestoreFolder, sourceWorkspacesFolder, dd);

        // Restore GeoServer Plugins
        final GeoServerResourceLoader sourceGeoServerResourceLoader = new GeoServerResourceLoader(
                sourceRestoreFolder.dir());
        for (GeoServerPluginConfigurator pluginConfig : GeoServerExtensions
                .extensions(GeoServerPluginConfigurator.class)) {
            // On restore invoke 'pluginConfig.loadConfiguration(resourceLoader);'. Replace 'properties' files first.
            for (Resource configFile : pluginConfig.getFileLocations()) {
                replaceConfigFile(sourceGeoServerResourceLoader, configFile);
            }

            // - Invoke 'pluginConfig.loadConfiguration' from the GOSERVER_DATA_DIR
            pluginConfig.loadConfiguration(dd.getResourceLoader());
        }

        for (GeoServerPropertyConfigurer props : GeoServerExtensions
                .extensions(GeoServerPropertyConfigurer.class)) {
            // On restore invoke 'props.reload();' after having replaced the properties files.
            Resource configFile = props.getConfigFile();
            replaceConfigFile(sourceGeoServerResourceLoader, configFile);

            // - Invoke 'props.reload()' from the GOSERVER_DATA_DIR
            props.reload();
        }

        // Restore other configuration bits, like images, palettes, user projections and so on...
        backupRestoreAdditionalResources(sourceGeoServerResourceLoader, dd.get(Paths.BASE));

        // Restore GWC Configuration bits
        try {
            if (GeoServerExtensions.bean("gwcGeoServervConfigPersister") != null) {
                restoreGWCSettings(sourceRestoreFolder, dd.get(Paths.BASE));

                // Initialize GWC with the new settings
                GWCInitializer gwcInitializer = GeoServerExtensions.bean(GWCInitializer.class);
                if (gwcInitializer != null) {
                    gwcInitializer.initialize(geoserver);
                }
            }
        } catch (NoSuchBeanDefinitionException e) {
            LOGGER.log(Level.WARNING, "Skipped GWC GeoServer Config Persister: ", e);
        }
    }

    /**
     * @param geoserver
     * @param td
     * @param sourceRestoreFolder
     * @param sourceWorkspacesFolder
     * @param newGeoServerInfo
     * @param newLoggingInfo
     * @throws Exception 
     */
    private void softRestore(final GeoServer geoserver, GeoServerDataDirectory td, Resource sourceRestoreFolder,
            Resource sourceWorkspacesFolder, GeoServerInfo newGeoServerInfo, LoggingInfo newLoggingInfo)
            throws Exception {
        // Restore GeoServer Global Info
        doWrite(newGeoServerInfo, td.get(Paths.BASE), "global.xml");

        // Restore GeoServer Global Logging Settings
        doWrite(newLoggingInfo, td.get(Paths.BASE), "logging.xml");

        // Restore GeoServer Global Services
        restoreGlobalServices(sourceRestoreFolder, td);

        // Restore Workspaces
        // - Prepare folder
        BackupUtils.dir(td.get(Paths.BASE), "workspaces");
        Resource workspaces = td.get("workspaces");

        restoreWorkSpacesAndLayers(workspaces);

        // Restore Styles
        // - Prepare folder
        BackupUtils.dir(td.get(Paths.BASE), "styles");
        Resource styles = td.get("styles");

        restoreGlobalStyles(sourceRestoreFolder, styles);

        // Restore LayerGroups
        // - Prepare folder
        BackupUtils.dir(td.get(Paths.BASE), "layergroups");
        Resource layerGroups = td.get("layergroups");

        // Workspace Local LayerGroups
        restoreGlobalLayerGroups(layerGroups);

        // Restore Workspace Specific Settings and Services
        restoreLocalWorkspaceSettingsAndServices(geoserver, sourceRestoreFolder, sourceWorkspacesFolder, td);

        // Restore GeoServer Plugins
        final GeoServerResourceLoader sourceGeoServerResourceLoader = new GeoServerResourceLoader(
                sourceRestoreFolder.dir());

        // Restore other configuration bits, like images, palettes, user projections and so on...
        backupRestoreAdditionalResources(sourceGeoServerResourceLoader, td.get(Paths.BASE));

        // Restore GWC Configuration bits
        try {
            if (GeoServerExtensions.bean("gwcGeoServervConfigPersister") != null) {
                restoreGWCSettings(sourceRestoreFolder, td.get(Paths.BASE));
            }
        } catch (NoSuchBeanDefinitionException e) {
            LOGGER.log(Level.WARNING, "Skipped GWC GeoServer Config Persister: ", e);
        }

        // Cleanup Temp Folder
        Files.delete(td.get(Paths.BASE).dir());
    }

    /**
     * @param resourceLoader
     * @param configFile
     * @throws IOException
     */
    private void replaceConfigFile(final GeoServerResourceLoader resourceLoader, Resource configFile)
            throws IOException {
        // - Check of the resource exists on the restore folder
        Resource rstConfigFile = Files.asResource(
                resourceLoader.find(Paths.path(configFile.file().getParent(), configFile.file().getName())));

        // - Copy the resource into the GOSERVER_DATA_DIR (overwriting the old one if exists)
        if (Resources.exists(rstConfigFile)) {
            Resources.copy(rstConfigFile.file(), configFile.parent());
        }
    }

    /**
     * @param geoserver
     * @param sourceRestoreFolder
     * @param sourceWorkspacesFolder
     * @param dd
     * @throws Exception 
     */
    private void restoreLocalWorkspaceSettingsAndServices(final GeoServer geoserver, Resource sourceRestoreFolder,
            Resource sourceWorkspacesFolder, GeoServerDataDirectory dd) throws Exception {
        for (WorkspaceInfo ws : geoserver.getCatalog().getWorkspaces()) {
            if (filteredWorkspace(ws)) {
                Resource wsFolder = BackupUtils.dir(sourceWorkspacesFolder, ws.getName());
                SettingsInfo wsSettings = null;
                if (Resources.exists(wsFolder.get("settings.xml"))) {
                    wsSettings = (SettingsInfo) doRead(wsFolder, "settings.xml");
                }

                if (wsSettings != null) {
                    wsSettings.setWorkspace(ws);
                    if (!isDryRun()) {
                        geoserver.add(wsSettings);
                        doWrite(geoserver.getSettings(ws), dd.get(Paths.path("workspaces", ws.getName())),
                                "settings.xml");
                    } else {
                        doWrite(wsSettings, dd.get(Paths.path("workspaces", ws.getName())), "settings.xml");
                    }
                }

                // Restore Workspace Local Services
                List<Resource> serviceResources = Resources.list(wsFolder, new Filter<Resource>() {

                    @Override
                    public boolean accept(Resource res) {
                        if (!"settings.xml".equals(res.name()) && res.name().endsWith(".xml")) {
                            return true;
                        }
                        return false;
                    }

                });
                for (Resource serviceResource : serviceResources) {
                    ServiceInfo localService = (ServiceInfo) doRead(wsFolder, serviceResource.name());
                    if (localService != null) {
                        localService.setWorkspace(ws);
                        if (!isDryRun()) {
                            geoserver.add(localService);
                        }
                        doWrite(localService, dd.get(Paths.path("workspaces", ws.getName())), "");
                    }
                }

                // Restore Local Styles
                for (StyleInfo sty : getCatalog().getStylesByWorkspace(ws.getName())) {
                    // Only Local Services here.
                    sty.setWorkspace(ws);
                    Resource wsLocalStyleFolder = BackupUtils.dir(dd.get(Paths.path("workspaces", ws.getName())),
                            "styles");
                    doWrite(sty, wsLocalStyleFolder, sty.getName() + ".xml");

                    Resource styResource = sourceRestoreFolder
                            .get(Paths.path("workspaces", ws.getName(), "styles", sty.getFilename()));
                    if (Resources.exists(styResource)) {
                        Resources.copy(styResource.file(), wsLocalStyleFolder);
                    }
                }

                // Restore Local LayerGroups
                for (LayerGroupInfo lyg : getCatalog().getLayerGroupsByWorkspace(ws.getName())) {
                    // Only Local LayerGroups here.
                    lyg.setWorkspace(ws);
                    Resource wsLocalLayerGroupsFolder = BackupUtils
                            .dir(dd.get(Paths.path("workspaces", ws.getName())), "layergroups");
                    doWrite(lyg, wsLocalLayerGroupsFolder, lyg.getName() + ".xml");
                }
            }
        }
    }

    /**
     * @param layerGroups
     * @throws Exception 
     */
    private void restoreGlobalLayerGroups(Resource layerGroups) throws Exception {
        for (LayerGroupInfo lyg : getCatalog().getLayerGroups()) {
            // Only Global LayerGroups here; local ones will be restored later on
            if (lyg.getWorkspace() == null) {
                doWrite(lyg, layerGroups, lyg.getName() + ".xml");
            }
        }
    }

    /**
     * @param sourceRestoreFolder
     * @param styles
     * @throws Exception 
     */
    private void restoreGlobalStyles(Resource sourceRestoreFolder, Resource styles) throws Exception {
        for (StyleInfo sty : getCatalog().getStyles()) {
            // Only Global Styles here. Local ones will be restored later on
            if (sty.getWorkspace() == null) {
                doWrite(sty, styles, sty.getName() + ".xml");

                Resource styResource = sourceRestoreFolder.get(Paths.path("styles", sty.getFilename()));
                if (Resources.exists(styResource)) {
                    Resources.copy(styResource.file(), styles);
                }
            }
        }
    }

    /**
     * @param sourceRestoreFolder
     * @param td
     * @throws Exception 
     */
    private void restoreGlobalServices(Resource sourceRestoreFolder, GeoServerDataDirectory td) throws Exception {
        for (Resource serviceResource : sourceRestoreFolder.get("services").list()) {
            // Local Services will be saved later on ...
            ServiceInfo service = (ServiceInfo) doRead(sourceRestoreFolder.get("services"), serviceResource.name());
            if (service != null && service.getWorkspace() == null) {
                Files.delete(td.get(serviceResource.name()).file());
                Resources.copy(sourceRestoreFolder.get(Paths.path("services", serviceResource.name())).file(),
                        td.get(Paths.BASE));
            }
        }
    }

    /**
     * @param workspaces
     * @throws Exception
     */
    private void restoreWorkSpacesAndLayers(Resource workspaces) throws Exception {
        // - Restore Default Workspace
        Files.delete(workspaces.get("default.xml").file());
        doWrite(getCatalog().getDefaultWorkspace(), workspaces, "default.xml");

        // - Restore Workspaces/Namespaces definitions and settings
        for (WorkspaceInfo ws : getCatalog().getWorkspaces()) {
            if (filteredWorkspace(ws)) {
                // Restore Workspace and Namespace confifuration
                // - Prepare Folder
                Files.delete(workspaces.get(ws.getName()).dir());
                Resource wsFolder = BackupUtils.dir(workspaces, ws.getName());

                doWrite(getCatalog().getNamespaceByPrefix(ws.getName()), wsFolder, "namespace.xml");
                doWrite(ws, wsFolder, "workspace.xml");

                // Restore DataStores/CoverageStores
                for (DataStoreInfo ds : getCatalog().getStoresByWorkspace(ws.getName(), DataStoreInfo.class)) {
                    // - Prepare Folder
                    Resource dsFolder = BackupUtils.dir(wsFolder, ds.getName());

                    ds.setWorkspace(ws);

                    doWrite(ds, dsFolder, "datastore.xml");

                    // Restore Resources
                    for (FeatureTypeInfo ft : getCatalog().getFeatureTypesByDataStore(ds)) {
                        // - Prepare Folder
                        Files.delete(dsFolder.get(ft.getName()).dir());
                        Resource ftFolder = BackupUtils.dir(dsFolder, ft.getName());

                        doWrite(ft, ftFolder, "featuretype.xml");

                        // Restore Layers
                        for (LayerInfo ly : getCatalog().getLayers(ft)) {
                            doWrite(ly, ftFolder, "layer.xml");
                        }
                    }
                }

                for (CoverageStoreInfo cs : getCatalog().getStoresByWorkspace(ws.getName(),
                        CoverageStoreInfo.class)) {
                    // - Prepare Folder
                    Resource csFolder = BackupUtils.dir(wsFolder, cs.getName());

                    cs.setWorkspace(ws);

                    doWrite(cs, csFolder, "coveragestore.xml");

                    // Restore Resources
                    for (CoverageInfo ci : getCatalog().getCoveragesByCoverageStore(cs)) {
                        // - Prepare Folder
                        Files.delete(csFolder.get(ci.getName()).dir());
                        Resource ciFolder = BackupUtils.dir(csFolder, ci.getName());

                        doWrite(ci, ciFolder, "coverage.xml");

                        // Restore Layers
                        for (LayerInfo ly : getCatalog().getLayers(ci)) {
                            doWrite(ly, ciFolder, "layer.xml");
                        }
                    }
                }
            }
        }
    }

    // ////////////////////////////////////////////////////////////////////////////////////// //
    //
    // GWC Stuff
    // ////////////////////////////////////////////////////////////////////////////////////// //
    /**
     * @param targetBackupFolder
     * @throws Exception
     */
    private void backupGWCSettings(Resource targetBackupFolder) throws Exception {
        GWCConfigPersister gwcGeoServerConfigPersister = (GWCConfigPersister) GeoServerExtensions
                .bean("gwcGeoServervConfigPersister");

        GWCConfigPersister testGWCCP = new GWCConfigPersister(getxStreamPersisterFactory(),
                new GeoServerResourceLoader(targetBackupFolder.dir()));

        // Test that everything went well
        try {
            testGWCCP.save(gwcGeoServerConfigPersister.getConfig());

            GWCConfig gwcConfig = testGWCCP.getConfig();

            Assert.notNull(gwcConfig);

            // TODO: perform more tests and integrity checks on reloaded configuration

            // Store GWC Providers Configurations
            Resource targetGWCProviderBackupDir = BackupUtils.dir(targetBackupFolder,
                    GeoserverXMLResourceProvider.DEFAULT_CONFIGURATION_DIR_NAME);

            for (GeoserverXMLResourceProvider gwcProvider : GeoServerExtensions
                    .extensions(GeoserverXMLResourceProvider.class)) {
                Resource providerConfigFile = Resources.fromPath(gwcProvider.getLocation());
                if (Resources.exists(providerConfigFile) && FileUtils.sizeOf(providerConfigFile.file()) > 0) {
                    Resources.copy(gwcProvider.in(), targetGWCProviderBackupDir, providerConfigFile.name());
                }
            }

            // Store GWC Layers Configurations
            // TODO: This should be done using the spring-batch item reader/writer, since it is not safe to save tons of single XML files.
            //       Nonetheless, given the default implementation of GWC Catalog does not have much sense to refactor this code now.
            final TileLayerCatalog gwcCatalog = (TileLayerCatalog) GeoServerExtensions
                    .bean("GeoSeverTileLayerCatalog");

            if (gwcCatalog != null) {
                final XMLConfiguration gwcXmlPersisterFactory = (XMLConfiguration) GeoServerExtensions
                        .bean("gwcXmlConfig");
                final GeoServerResourceLoader resourceLoader = new GeoServerResourceLoader(
                        targetBackupFolder.dir());

                final DefaultTileLayerCatalog gwcBackupCatalog = new DefaultTileLayerCatalog(resourceLoader,
                        gwcXmlPersisterFactory);

                for (String layerName : gwcCatalog.getLayerNames()) {
                    GeoServerTileLayerInfo gwcLayerInfo = gwcCatalog.getLayerByName(layerName);

                    // Persist the GWC Layer Info into the backup folder
                    boolean persistResource = false;

                    LayerInfo layerInfo = getCatalog().getLayerByName(layerName);

                    if (layerInfo != null) {

                        WorkspaceInfo ws = layerInfo.getResource() != null
                                && layerInfo.getResource().getStore() != null
                                && layerInfo.getResource().getStore().getWorkspace() != null
                                        ? getCatalog().getWorkspaceByName(
                                                layerInfo.getResource().getStore().getWorkspace().getName())
                                        : null;

                        if (!filteredResource(layerInfo, ws, true)) {
                            persistResource = true;
                        }
                    } else {
                        LayerGroupInfo layerGroupInfo = getCatalog().getLayerGroupByName(layerName);

                        if (layerGroupInfo != null) {

                            WorkspaceInfo ws = layerGroupInfo.getWorkspace() != null
                                    ? getCatalog().getWorkspaceByName(layerGroupInfo.getWorkspace().getName())
                                    : null;

                            if (!filteredResource(layerGroupInfo, ws, false)) {
                                persistResource = true;
                            }
                        }
                    }

                    if (persistResource) {
                        gwcBackupCatalog.save(gwcLayerInfo);
                    }
                }
            }

        } catch (Exception e) {
            logValidationExceptions(null, e);
        }
    }

    /**
     * TODO: When Restoring
     * 
     * 1. the securityManager should issue the listeners 2. the GWCInitializer should be re-initialized
     * 
     * @param sourceRestoreFolder
     * @param baseDir
     * @throws Exception
     * @throws IOException
     */
    private void restoreGWCSettings(Resource sourceRestoreFolder, Resource baseDir) throws Exception {
        // Restore configuration files form source and Test that everything went well
        try {

            // - Prepare folder
            GeoserverXMLResourceProvider gwcConfigProvider = (GeoserverXMLResourceProvider) GeoServerExtensions
                    .bean("gwcXmlConfigResourceProvider");
            Resource targetGWCProviderRestoreDir = gwcConfigProvider.getConfigDirectory();
            Files.delete(targetGWCProviderRestoreDir.dir());

            // Restore GWC Providers Configurations
            for (GeoserverXMLResourceProvider gwcProvider : GeoServerExtensions
                    .extensions(GeoserverXMLResourceProvider.class)) {
                Resource providerConfigFile = sourceRestoreFolder
                        .get(Paths.path(GeoserverXMLResourceProvider.DEFAULT_CONFIGURATION_DIR_NAME,
                                gwcProvider.getConfigFileName()));
                if (Resources.exists(providerConfigFile) && FileUtils.sizeOf(providerConfigFile.file()) > 0) {
                    Resources.copy(providerConfigFile.in(), targetGWCProviderRestoreDir, providerConfigFile.name());
                }
            }

            // Restore GWC Layers Configurations
            // TODO: This should be done using the spring-batch item reader/writer, since it is not safe to save tons of single XML files.
            //       Nonetheless, given the default implementation of GWC Catalog does not have much sense to refactor this code now.
            final TileLayerCatalog gwcCatalog = (TileLayerCatalog) GeoServerExtensions
                    .bean("GeoSeverTileLayerCatalog");
            BiMap<String, String> layersByName = null;

            if (gwcCatalog != null) {

                if (isDryRun()) {
                    BiMap<String, String> baseBiMap = HashBiMap.create();
                    layersByName = Maps.synchronizedBiMap(baseBiMap);
                }

                final XMLConfiguration gwcXmlPersisterFactory = (XMLConfiguration) GeoServerExtensions
                        .bean("gwcXmlConfig");
                final GeoServerResourceLoader resourceLoader = new GeoServerResourceLoader(
                        sourceRestoreFolder.dir());

                final DefaultTileLayerCatalog gwcRestoreCatalog = new DefaultTileLayerCatalog(resourceLoader,
                        gwcXmlPersisterFactory);

                for (String layerName : gwcRestoreCatalog.getLayerNames()) {
                    GeoServerTileLayerInfo gwcLayerInfo = gwcRestoreCatalog.getLayerByName(layerName);

                    LayerInfo layerInfo = getCatalog().getLayerByName(layerName);

                    if (layerInfo != null) {

                        WorkspaceInfo ws = layerInfo.getResource() != null
                                && layerInfo.getResource().getStore() != null
                                && layerInfo.getResource().getStore().getWorkspace() != null
                                        ? getCatalog().getWorkspaceByName(
                                                layerInfo.getResource().getStore().getWorkspace().getName())
                                        : null;

                        if (!filteredResource(layerInfo, ws, true)) {
                            restoreGWCTileLayerInfo(gwcCatalog, layersByName, layerName, gwcLayerInfo,
                                    layerInfo.getId());
                        }
                    } else {
                        LayerGroupInfo layerGroupInfo = getCatalog().getLayerGroupByName(layerName);

                        if (layerGroupInfo != null) {

                            WorkspaceInfo ws = layerGroupInfo.getWorkspace() != null
                                    ? getCatalog().getWorkspaceByName(layerGroupInfo.getWorkspace().getName())
                                    : null;

                            if (!filteredResource(layerGroupInfo, ws, false)) {
                                restoreGWCTileLayerInfo(gwcCatalog, layersByName, layerName, gwcLayerInfo,
                                        layerGroupInfo.getId());
                            }
                        }
                    }
                }
            }

        } catch (Exception e) {
            logValidationExceptions(null, e);
        }
    }

    /**
     * @param gwcCatalog
     * @param layersByName
     * @param layerName
     * @param gwcLayerInfo
     * @param layerInfo
     * @throws IllegalArgumentException
     */
    private void restoreGWCTileLayerInfo(final TileLayerCatalog gwcCatalog, BiMap<String, String> layersByName,
            String layerName, GeoServerTileLayerInfo gwcLayerInfo, String layerID) throws IllegalArgumentException {
        if (!isDryRun()) {
            // - Depersist the GWC Layer Info into the restore folder
            GeoServerTileLayerInfo oldValue = gwcCatalog.getLayerByName(layerName);
            gwcCatalog.delete(oldValue.getId());

            // - Update the ID
            gwcLayerInfo.setId(layerID);
            gwcCatalog.save(gwcLayerInfo);
        } else {
            if (layersByName.get(layerName) == null) {
                layersByName.put(layerName, layerID);
            } else {
                // - Warning or Exception
                throw new IllegalArgumentException(
                        "TileLayer with same name already exists: " + layerName + ": <" + layerID + ">");
            }
        }
    }
}