/* (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.imagemosaic.reader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.Map.Entry;
import java.util.Properties;
import org.apache.commons.io.FilenameUtils;
import org.geoserver.backuprestore.Backup;
import org.geoserver.backuprestore.imagemosaic.ImageMosaicAdditionalResource;
import org.geoserver.backuprestore.reader.CatalogAdditionalResourcesReader;
import org.geoserver.backuprestore.utils.BackupUtils;
import org.geoserver.catalog.CoverageStoreInfo;
import org.geoserver.catalog.StoreInfo;
import org.geoserver.platform.GeoServerEnvironment;
import org.geoserver.platform.GeoServerExtensions;
import org.geoserver.platform.resource.Resource;
import org.geoserver.platform.resource.Resources;
/**
* @author Alessio Fabiani, GeoSolutions
*
*/
public class ImageMosaicAdditionalResourceReader extends ImageMosaicAdditionalResource
implements CatalogAdditionalResourcesReader<StoreInfo> {
final GeoServerEnvironment gsEnvironment = GeoServerExtensions.bean(GeoServerEnvironment.class);
@Override
public boolean canHandle(Object item) {
if (item instanceof CoverageStoreInfo
&& ((CoverageStoreInfo) item).getType().equals(COVERAGE_TYPE)) {
return true;
}
return false;
}
@Override
public void readAdditionalResources(Backup backupFacade, Resource base, StoreInfo item)
throws IOException {
final Resource sourceBackupFolder = BackupUtils.dir(base.parent(),
IMAGEMOSAIC_INDEXES_FOLDER);
final CoverageStoreInfo mosaicCoverageStore =
backupFacade.getCatalog().getResourcePool().clone((CoverageStoreInfo) item, true);
final String mosaicName = mosaicCoverageStore.getName();
final String mosaicUrlBase = mosaicCoverageStore.getURL();
final Resource mosaicIndexBase = Resources.fromURL(mosaicUrlBase);
List<Resource> mosaicIndexerResources = Resources.list(sourceBackupFolder,
resources.get("properties"), true);
mosaicIndexerResources.addAll(Resources.list(sourceBackupFolder,
resources.get("info"), true));
boolean datastoreAlreadyPresent = true;
for (Resource res : mosaicIndexerResources) {
if (!FilenameUtils.getBaseName(res.name()).equals(mosaicName) && Resources.exists(res)
&& Resources.canRead(res)) {
boolean result = copyFile(sourceBackupFolder, mosaicIndexBase, res, false);
if (result && FilenameUtils.getBaseName(res.name()).equals("datastore")) {
// The copy of the new "datastore.properties" was successful, meaning that
// there wasn't an other copy of that file on the target folder.
datastoreAlreadyPresent = false;
}
}
}
List<Resource> mosaicIndexerTemplateResources = Resources.list(sourceBackupFolder,
resources.get("templates"), true);
for (Resource res : mosaicIndexerTemplateResources) {
if (Resources.exists(res) && Resources.canRead(res)) {
boolean result = copyFile(sourceBackupFolder, mosaicIndexBase, res, true);
if (result) {
resolveTemplate(sourceBackupFolder, mosaicIndexBase, res);
}
}
}
if (!datastoreAlreadyPresent) {
// Sine there wasn't already a "datasotre.properties" on the target folder
// we assume this is a new mosaic.
// We need to be sure the property "CanBeEmpty=true" is present on the
// "indexer.properties"
final File indexerFile = new File(mosaicIndexBase.dir(), "indexer.properties");
Properties indexerProperties = new Properties();
if (indexerFile.exists() && indexerFile.canRead()) {
indexerProperties.load(new FileInputStream(indexerFile));
}
indexerProperties.setProperty("CanBeEmpty", "true");
indexerProperties.store(new FileOutputStream(indexerFile), null);
}
}
/**
* @param sourceBackupFolder
* @param mosaicIndexBase
* @param res
* @throws IOException
* @throws FileNotFoundException
*/
private void resolveTemplate(final Resource sourceBackupFolder, final Resource mosaicIndexBase,
Resource res) throws IOException, FileNotFoundException {
// Overwrite target .properties file by resolving template placeholders
Properties templateProperties = new Properties();
templateProperties.load(res.in());
Properties resolvedProperties = new Properties();
for (Entry<Object, Object> propEntry : templateProperties.entrySet()) {
String value = (String) propEntry.getValue();
if (GeoServerEnvironment.ALLOW_ENV_PARAMETRIZATION) {
value = (String) gsEnvironment.resolveValue(value);
}
resolvedProperties.setProperty((String) propEntry.getKey(), value);
}
final String relative = sourceBackupFolder.dir().toURI()
.relativize(res.file().toURI()).getPath();
final String targetPropertyFileName = relative.substring(0,
relative.length() - ".template".length());
final File targetFile = new File(mosaicIndexBase.parent().dir(),
targetPropertyFileName);
resolvedProperties.store(new FileOutputStream(targetFile), null);
}
/**
* @param sourceBackupFolder
* @param mosaicIndexBase
* @param res
* @throws IOException
*/
private boolean copyFile(final Resource sourceBackupFolder, final Resource mosaicIndexBase,
Resource res, boolean overwrite) throws IOException {
final String relative = sourceBackupFolder.dir().toURI().relativize(res.file().toURI())
.getPath();
Resource targetFtl = Resources.fromPath(relative, mosaicIndexBase.parent());
if (!Resources.exists(targetFtl) || overwrite) {
if (!targetFtl.parent().dir().exists()) {
targetFtl.parent().dir().mkdirs();
}
Resources.copy(res.file(), targetFtl.parent());
return true;
}
return false;
}
}