/* (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 + ">");
}
}
}
}