Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.springframework.data.gemfire.snapshot.SnapshotServiceFactoryBean Maven / Gradle / Ivy
/*
* Copyright 2010-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire.snapshot;
import static java.util.Arrays.stream;
import static org.apache.geode.cache.snapshot.SnapshotOptions.SnapshotFormat;
import static org.springframework.data.gemfire.snapshot.SnapshotServiceFactoryBean.SnapshotServiceAdapter;
import static org.springframework.data.gemfire.util.ArrayUtils.nullSafeArray;
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalArgumentException;
import static org.springframework.data.gemfire.util.RuntimeExceptionFactory.newIllegalStateException;
import java.io.Closeable;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.jar.JarFile;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import org.apache.geode.cache.Cache;
import org.apache.geode.cache.Region;
import org.apache.geode.cache.snapshot.CacheSnapshotService;
import org.apache.geode.cache.snapshot.RegionSnapshotService;
import org.apache.geode.cache.snapshot.SnapshotFilter;
import org.apache.geode.cache.snapshot.SnapshotOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.ApplicationListener;
import org.springframework.data.gemfire.snapshot.event.ExportSnapshotApplicationEvent;
import org.springframework.data.gemfire.snapshot.event.SnapshotApplicationEvent;
import org.springframework.data.gemfire.support.AbstractFactoryBeanSupport;
import org.springframework.data.gemfire.util.CollectionUtils;
import org.springframework.util.Assert;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;
/**
* The SnapshotServiceFactoryBean class is a Spring FactoryBean used to configure and create an instance
* of an appropriate Pivotal GemFire Snapshot Service to perform data import and exports. A CacheSnapshotService is created
* if the Region is not specified, otherwise a RegionSnapshotService is used based on the configured Region.
*
* @author John Blum
* @see org.springframework.beans.factory.DisposableBean
* @see org.springframework.beans.factory.FactoryBean
* @see org.springframework.beans.factory.InitializingBean
* @see org.springframework.context.ApplicationListener
* @see org.springframework.data.gemfire.snapshot.SnapshotServiceFactoryBean.SnapshotServiceAdapter
* @see org.apache.geode.cache.snapshot.CacheSnapshotService
* @see org.apache.geode.cache.snapshot.RegionSnapshotService
* @since 1.7.0
*/
@SuppressWarnings("unused")
public class SnapshotServiceFactoryBean extends AbstractFactoryBeanSupport>
implements InitializingBean, DisposableBean, ApplicationListener> {
protected static final SnapshotMetadata[] EMPTY_ARRAY = new SnapshotMetadata[0];
private Boolean suppressImportOnInit;
private Cache cache;
private Region region;
private SnapshotMetadata[] exports;
private SnapshotMetadata[] imports;
private SnapshotServiceAdapter snapshotServiceAdapter;
static boolean nullSafeIsDirectory(File file) {
return file != null && file.isDirectory();
}
static boolean nullSafeIsFile(File file) {
return file != null && file.isFile();
}
/**
* Constructs and initializes the Pivotal GemFire Snapshot Service used to take a snapshot of the configured Cache
* or Region if initialized. In addition, this initialization method will perform the actual import.
*
* @throws Exception if the construction and initialization of the Pivotal GemFire Snapshot Service fails.
* @see org.springframework.data.gemfire.snapshot.SnapshotServiceFactoryBean.SnapshotServiceAdapter
* @see #getSuppressImportOnInit()
* @see #getImports()
* @see #create()
*/
@Override
@SuppressWarnings("unchecked")
public void afterPropertiesSet() throws Exception {
this.snapshotServiceAdapter = create();
if (!getSuppressImportOnInit()) {
this.snapshotServiceAdapter.doImport(getImports());
}
}
/**
* Constructs an appropriate instance of the SnapshotServiceAdapter based on the FactoryBean configuration. If
* a Region has not been specified, then a Pivotal GemFire Snapshot Service for the Cache is constructed, otherwise
* the Pivotal GemFire Snapshot Service for the configured Region is used.
*
* @return a SnapshotServiceAdapter wrapping the appropriate Pivotal GemFire Snapshot Service (either Cache or Region)
* depending on the FactoryBean configuration.
* @see #wrap(CacheSnapshotService)
* @see #wrap(RegionSnapshotService)
* @see #getRegion()
*/
protected SnapshotServiceAdapter create() {
return Optional.ofNullable(getRegion())
.map(region -> wrap(region.getSnapshotService()))
.orElseGet(() -> wrap(getCache().getSnapshotService()));
}
/**
* Wraps the Pivotal GemFire CacheSnapshotService into an appropriate Adapter to uniformly access snapshot operations
* on the Cache and Regions alike.
*
* @param cacheSnapshotService the Pivotal GemFire CacheSnapshotService to wrap.
* @return a SnapshotServiceAdapter wrapping the Pivotal GemFire CacheSnapshotService.
* @see SnapshotServiceFactoryBean.SnapshotServiceAdapter
* @see SnapshotServiceFactoryBean.CacheSnapshotServiceAdapter
* @see org.apache.geode.cache.snapshot.CacheSnapshotService
*/
protected SnapshotServiceAdapter wrap(CacheSnapshotService cacheSnapshotService) {
return new CacheSnapshotServiceAdapter(cacheSnapshotService);
}
/**
* Wraps Pivotal GemFire's RegionSnapshotService into an appropriate Adapter to uniformly access snapshot operations
* on the Cache and Regions alike.
*
* @param regionSnapshotService the Pivotal GemFire RegionSnapshotService to wrap.
* @return a SnapshotServiceAdapter wrapping the Pivotal GemFire RegionSnapshotService.
* @see SnapshotServiceFactoryBean.SnapshotServiceAdapter
* @see SnapshotServiceFactoryBean.RegionSnapshotServiceAdapter
* @see org.apache.geode.cache.snapshot.RegionSnapshotService
*/
protected SnapshotServiceAdapter wrap(RegionSnapshotService regionSnapshotService) {
return new RegionSnapshotServiceAdapter<>(regionSnapshotService);
}
/**
* Sets a reference to the Pivotal GemFire Cache for which the snapshot will be taken.
*
* @param cache the Pivotal GemFire Cache used to create an instance of CacheSnapshotService.
* @throws IllegalArgumentException if the Cache reference is null.
* @see org.apache.geode.cache.Cache
* @see #getCache()
*/
public void setCache(Cache cache) {
this.cache = Optional.ofNullable(cache)
.orElseThrow(() -> newIllegalArgumentException("Cache must not be null"));
}
/**
* Gets a reference to the Pivotal GemFire Cache for which the snapshot will be taken.
*
* @return the Pivotal GemFire Cache used to create an instance of CacheSnapshotService.
* @throws IllegalStateException if the Cache argument is null.
* @see org.apache.geode.cache.Cache
* @see #setCache(Cache)
*/
protected Cache getCache() {
return Optional.ofNullable(this.cache)
.orElseThrow(() -> newIllegalStateException("The cache was not properly initialized"));
}
/**
* Sets the meta-data (location, filter and format) used to create a snapshot from the Cache or Region data.
*
* @param exports an array of snapshot meta-data used for each export.
* @see SnapshotServiceFactoryBean.SnapshotMetadata
*/
public void setExports(SnapshotMetadata[] exports) {
this.exports = exports;
}
/**
* Sets the meta-data (location, filter and format) used to create a snapshot from the Cache or Region data.
*
* @return an array of snapshot meta-data used for each export.
* @see SnapshotServiceFactoryBean.SnapshotMetadata
*/
@SuppressWarnings("unchecked")
protected SnapshotMetadata[] getExports() {
return nullSafeArray(exports, SnapshotMetadata.class);
}
/**
* Sets the meta-data (location, filter and format) used to read a data snapshot into an entire Cache
* or individual Region.
*
* @param imports an array of snapshot meta-data used for each import.
* @see SnapshotServiceFactoryBean.SnapshotMetadata
*/
public void setImports(SnapshotMetadata[] imports) {
this.imports = imports;
}
/**
* Gets the meta-data (location, filter and format) used to read a data snapshot into an entire Cache
* or individual Region.
*
* @return an array of snapshot meta-data used for each import.
* @see SnapshotServiceFactoryBean.SnapshotMetadata
*/
@SuppressWarnings("unchecked")
protected SnapshotMetadata[] getImports() {
return nullSafeArray(imports, SnapshotMetadata.class);
}
/**
* Sets a reference to the Pivotal GemFire Region for which the snapshot will be taken.
*
* @param region the Pivotal GemFire Region used to create an instance of the RegionSnapshotService.
* @see org.apache.geode.cache.Region
* @see #getRegion()
*/
public void setRegion(Region region) {
this.region = region;
}
/**
* Gets a reference to the Pivotal GemFire Region for which the snapshot will be taken.
*
* @return the Pivotal GemFire Region used to create an instance of the RegionSnapshotService.
* @see org.apache.geode.cache.Region
* @see #getRegion()
*/
protected Region getRegion() {
return this.region;
}
/**
* Sets a boolean condition to indicate whether importing on initialization should be suppressed.
*
* @param suppressImportOnInit a Boolean value to indicate whether importing on initialization should be suppressed.
* @see #getSuppressImportOnInit()
*/
public void setSuppressImportOnInit(Boolean suppressImportOnInit) {
this.suppressImportOnInit = suppressImportOnInit;
}
/**
* Determines whether importing on initialization should be suppressed.
*
* @return a boolean value indicating whether import on initialization should be suppressed.
* @see #setSuppressImportOnInit(Boolean)
* @see #afterPropertiesSet()
*/
protected boolean getSuppressImportOnInit() {
return Boolean.TRUE.equals(suppressImportOnInit);
}
/**
* Gets the reference to the Pivotal GemFire Snapshot Service created by this FactoryBean.
*
* @return the Pivotal GemFire Snapshot Service created by this FactoryBean.
* @throws Exception if the Pivotal GemFire Snapshot Service failed to be created.
* @see SnapshotServiceFactoryBean.SnapshotServiceAdapter
*/
@Override
public SnapshotServiceAdapter getObject() throws Exception {
return this.snapshotServiceAdapter;
}
/**
* Gets the type of Snapshot Service created by this FactoryBean.
*
* @return a Class object representing the type of Snapshot Service created by this FactoryBean.
* @see SnapshotServiceFactoryBean.SnapshotServiceAdapter
* @see SnapshotServiceFactoryBean.CacheSnapshotServiceAdapter
* @see SnapshotServiceFactoryBean.RegionSnapshotServiceAdapter
*/
@Override
@SuppressWarnings("unchecked")
public Class getObjectType() {
return Optional.ofNullable(this.snapshotServiceAdapter)
.map(Object::getClass)
.orElse((Class) SnapshotServiceAdapter.class);
}
/**
* Determines this this FactoryBean creates single Pivotal GemFire Snapshot Service instances.
*
* @return true.
*/
@Override
public boolean isSingleton() {
return true;
}
/**
* Performs an export of the Pivotal GemFire Cache or Region if configured.
*
* @throws Exception if the Cache/Region data export operation fails.
* @see org.springframework.data.gemfire.snapshot.SnapshotServiceFactoryBean.SnapshotServiceAdapter
* @see #getExports()
* @see #getObject()
*/
@Override
@SuppressWarnings("all")
public void destroy() throws Exception {
getObject().doExport(getExports());
}
/**
* Listens for SnapshotApplicationEvents triggering a Pivotal GemFire Cache-wide or Region data snapshot import/export
* when details of the event match the criteria of this factory's constructed Pivotal GemFire SnapshotService.
*
* @param event the SnapshotApplicationEvent triggering a Pivotal GemFire Cache or Region data import/export.
* @see org.springframework.data.gemfire.snapshot.SnapshotServiceFactoryBean.SnapshotServiceAdapter
* @see org.springframework.data.gemfire.snapshot.event.ExportSnapshotApplicationEvent
* @see org.springframework.data.gemfire.snapshot.event.ImportSnapshotApplicationEvent
* @see org.springframework.data.gemfire.snapshot.event.SnapshotApplicationEvent
* @see #isMatch(SnapshotApplicationEvent)
* @see #resolveSnapshotMetadata(SnapshotApplicationEvent)
* @see #getObject()
*/
@Override
@SuppressWarnings("all")
public void onApplicationEvent(SnapshotApplicationEvent event) {
try {
if (isMatch(event)) {
if (event instanceof ExportSnapshotApplicationEvent) {
getObject().doExport(resolveSnapshotMetadata(event));
}
else {
getObject().doImport(resolveSnapshotMetadata(event));
}
}
}
catch (Exception ignore) { }
}
/**
* Determines whether the details of the given SnapshotApplicationEvent match the criteria of this factory
* to trigger a Pivotal GemFire Cache or Region data export.
*
* @param event the SnapshotApplicationEvent containing details of the application requested data export.
* @return a boolean value indicating whether the application requested snapshot event details match
* the criteria required by this factory to trigger a Pivotal GemFire Cache or Region data export.
* @see SnapshotApplicationEvent
*/
protected boolean isMatch(SnapshotApplicationEvent event) {
return event.isCacheSnapshotEvent() || event.matches(getRegion());
}
/**
* Resolves the SnapshotMetadata used to perform the Pivotal GemFire Cache or Region data snapshot import/export.
* If the event contains specific SnapshotMetadata, then this is preferred over the factory's own
* "import" or "export" SnapshotMetadata.
*
* @param event the SnapshotApplicationEvent from which to resolve the SnapshotMetadata.
* @return the resolved SnapshotMetadata, either from the event or this factory's configured imports/exports.
* @see SnapshotApplicationEvent#getSnapshotMetadata()
* @see #getExports()
* @see #getImports()
*/
protected SnapshotMetadata[] resolveSnapshotMetadata(SnapshotApplicationEvent event) {
SnapshotMetadata[] eventSnapshotMetadata = event.getSnapshotMetadata();
return !ObjectUtils.isEmpty(eventSnapshotMetadata)
? eventSnapshotMetadata
: (event instanceof ExportSnapshotApplicationEvent ? getExports() : getImports());
}
/**
* The SnapshotServiceAdapter interface is an Adapter adapting both Pivotal GemFire CacheSnapshotService
* and RegionSnapshotService to treat them uniformly.
*
* @param the class type of the Region key.
* @param the class type of the Region value.
*/
public interface SnapshotServiceAdapter {
SnapshotOptions createOptions();
@SuppressWarnings("unchecked")
void doExport(SnapshotMetadata... configurations);
@SuppressWarnings("unchecked")
void doImport(SnapshotMetadata... configurations);
void load(File directory, SnapshotFormat format);
void load(SnapshotFormat format, SnapshotOptions options, File... snapshots);
void save(File location, SnapshotFormat format);
void save(File location, SnapshotFormat format, SnapshotOptions options);
}
/**
* SnapshotServiceAdapterSupport is an abstract base class for all SnapshotServiceAdapter implementations
* encapsulating common reusable functionality.
*
* @param the class type of the Cache Region key.
* @param the class type of the Cache Region value.
* @see SnapshotServiceFactoryBean.SnapshotServiceAdapter
*/
protected static abstract class SnapshotServiceAdapterSupport implements SnapshotServiceAdapter {
protected static final File TEMPORARY_DIRECTORY = new File(System.getProperty("java.io.tmpdir"));
protected final Logger logger = createLog();
Logger createLog() {
return LoggerFactory.getLogger(getClass());
}
@Override
public SnapshotOptions createOptions() {
throw new UnsupportedOperationException("not implemented");
}
protected SnapshotOptions createOptions(SnapshotMetadata metadata) {
return createOptions()
.invokeCallbacks(metadata.isInvokeCallbacks())
.setFilter(metadata.getFilter())
.setParallelMode(metadata.isParallel());
}
@Override
@SuppressWarnings("unchecked")
public void doExport(SnapshotMetadata... configurations) {
stream(nullSafeArray(configurations, SnapshotMetadata.class)).forEach(configuration ->
save(configuration.getLocation(), configuration.getFormat(), createOptions(configuration)));
}
@Override
@SuppressWarnings("unchecked")
public void doImport(SnapshotMetadata... configurations) {
stream(nullSafeArray(configurations, SnapshotMetadata.class)).forEach(configuration ->
load(configuration.getFormat(), createOptions(configuration), handleLocation(configuration)));
}
protected abstract File[] handleLocation(SnapshotMetadata configuration);
protected File[] handleDirectoryLocation(File directory) {
return directory.listFiles(pathname -> nullSafeIsFile(pathname));
}
protected File[] handleFileLocation(File file) {
if (ArchiveFileFilter.INSTANCE.accept(file)) {
try {
File extractedArchiveDirectory =
new File(TEMPORARY_DIRECTORY, file.getName().replaceAll("\\.", "-"));
Assert.state(extractedArchiveDirectory.isDirectory() || extractedArchiveDirectory.mkdirs(),
String.format("Failed create directory (%1$s) in which to extract archive (%2$s)",
extractedArchiveDirectory, file));
ZipFile zipFile = (ArchiveFileFilter.INSTANCE.isJarFile(file)
? new JarFile(file, false, JarFile.OPEN_READ)
: new ZipFile(file, ZipFile.OPEN_READ));
for (ZipEntry entry : CollectionUtils.iterable(zipFile.entries())) {
if (!entry.isDirectory()) {
DataInputStream entryInputStream = new DataInputStream(zipFile.getInputStream(entry));
DataOutputStream entryOutputStream = new DataOutputStream(new FileOutputStream(
new File(extractedArchiveDirectory, toSimpleFilename(entry.getName()))));
try {
FileCopyUtils.copy(entryInputStream, entryOutputStream);
}
finally {
exceptionSuppressingClose(entryInputStream);
exceptionSuppressingClose(entryOutputStream);
}
}
}
return handleDirectoryLocation(extractedArchiveDirectory);
}
catch (Throwable cause) {
throw new ImportSnapshotException(
String.format("Failed to extract archive [%1$s] to import", file), cause);
}
}
return new File[] { file };
}
protected boolean exceptionSuppressingClose(Closeable closeable) {
try {
closeable.close();
return true;
}
catch (IOException cause) {
logDebug(cause, "Failed to close [%s]", closeable);
return false;
}
}
protected void logDebug(Throwable cause, String message, Object... arguments) {
if (logger.isDebugEnabled()) {
logger.debug(String.format(message, arguments), cause);
}
}
@Override
public void load(File directory, SnapshotFormat format) {
throw new UnsupportedOperationException("not implemented");
}
@Override
public void load(SnapshotFormat format, SnapshotOptions options, File... snapshots) {
throw new UnsupportedOperationException("not implemented");
}
@Override
public void save(File location, SnapshotFormat format) {
throw new UnsupportedOperationException("not implemented");
}
@Override
public void save(File location, SnapshotFormat format, SnapshotOptions options) {
throw new UnsupportedOperationException("not implemented");
}
protected String toSimpleFilename(String pathname) {
int pathSeparatorIndex = String.valueOf(pathname).lastIndexOf(File.separator);
pathname = (pathSeparatorIndex > -1 ? pathname.substring(pathSeparatorIndex + 1) : pathname);
return StringUtils.trimWhitespace(pathname);
}
}
/**
* The CacheSnapshotServiceAdapter is a SnapshotServiceAdapter adapting Pivotal GemFire's CacheSnapshotService.
*
* @see SnapshotServiceFactoryBean.SnapshotServiceAdapterSupport
*/
protected static class CacheSnapshotServiceAdapter extends SnapshotServiceAdapterSupport {
private final CacheSnapshotService snapshotService;
public CacheSnapshotServiceAdapter(CacheSnapshotService snapshotService) {
Assert.notNull(snapshotService, "The backing CacheSnapshotService must not be null");
this.snapshotService = snapshotService;
}
protected CacheSnapshotService getSnapshotService() {
return this.snapshotService;
}
@Override
public SnapshotOptions createOptions() {
return getSnapshotService().createOptions();
}
@Override
protected File[] handleLocation(SnapshotMetadata configuration) {
return configuration.isFile()
? handleFileLocation(configuration.getLocation())
: handleDirectoryLocation(configuration.getLocation());
}
@Override
public void load(File directory, SnapshotFormat format) {
try {
getSnapshotService().load(directory, format);
}
catch (Throwable cause) {
throw new ImportSnapshotException(String.format(
"Failed to load snapshots from directory [%1$s] in format [%2$s]",
directory, format), cause);
}
}
@Override
public void load(SnapshotFormat format, SnapshotOptions options, File... snapshots) {
try {
getSnapshotService().load(snapshots, format, options);
}
catch (Throwable cause) {
throw new ImportSnapshotException(String.format(
"Failed to load snapshots [%1$s] in format [%2$s] using options [%3$s]",
Arrays.toString(snapshots), format, options), cause);
}
}
@Override
public void save(File directory, SnapshotFormat format) {
try {
getSnapshotService().save(directory, format);
}
catch (Throwable cause) {
throw new ExportSnapshotException(String.format(
"Failed to save snapshots to directory [%1$s] in format [%2$s]",
directory, format), cause);
}
}
@Override
public void save(File directory, SnapshotFormat format, SnapshotOptions options) {
try {
getSnapshotService().save(directory, format, options);
}
catch (Throwable cause) {
throw new ExportSnapshotException(String.format(
"Failed to save snapshots to directory [%1$s] in format [%2$s] using options [%3$s]",
directory, format, options), cause);
}
}
}
/**
* The RegionSnapshotServiceAdapter is a SnapshotServiceAdapter adapting Pivotal GemFire's RegionSnapshotService.
*
* @see SnapshotServiceFactoryBean.SnapshotServiceAdapterSupport
*/
protected static class RegionSnapshotServiceAdapter extends SnapshotServiceAdapterSupport {
private final RegionSnapshotService snapshotService;
public RegionSnapshotServiceAdapter(RegionSnapshotService snapshotService) {
Assert.notNull(snapshotService, "The backing RegionSnapshotService must not be null");
this.snapshotService = snapshotService;
}
protected RegionSnapshotService getSnapshotService() {
return this.snapshotService;
}
@Override
public SnapshotOptions createOptions() {
return getSnapshotService().createOptions();
}
@Override
protected File[] handleLocation(SnapshotMetadata configuration) {
return new File[] { configuration.getLocation() };
}
@Override
public void load(File snapshot, SnapshotFormat format) {
try {
getSnapshotService().load(snapshot, format);
}
catch (Throwable cause) {
throw new ImportSnapshotException(String.format(
"Failed to load snapshot from file [%1$s] in format [%2$s]",
snapshot, format), cause);
}
}
@Override
public void load(SnapshotFormat format, SnapshotOptions options, File... snapshots) {
try {
for (File snapshot : snapshots) {
getSnapshotService().load(snapshot, format, options);
}
}
catch (Throwable cause) {
throw new ImportSnapshotException(String.format(
"Failed to load snapshots [%1$s] in format [%2$s] using options [%3$s]",
Arrays.toString(snapshots), format, options), cause);
}
}
@Override
public void save(File snapshot, SnapshotFormat format) {
try {
getSnapshotService().save(snapshot, format);
}
catch (Throwable cause) {
throw new ExportSnapshotException(String.format(
"Failed to save snapshot to file [%1$s] in format [%2$s]",
snapshot, format), cause);
}
}
@Override
public void save(File snapshot, SnapshotFormat format, SnapshotOptions options) {
try {
getSnapshotService().save(snapshot, format, options);
}
catch (Throwable cause) {
throw new ExportSnapshotException(String.format(
"Failed to save snapshot to file [%1$s] in format [%2$s] using options [%3$s]",
snapshot, format, options), cause);
}
}
}
/**
* The SnapshotMetadata class encapsulates details of the Pivotal GemFire Cache or Region data snapshot
* on either import or export.
*
* @param the class type of the Region key.
* @param the class type of the Region value.
*/
public static class SnapshotMetadata {
protected static final boolean DEFAULT_INVOKE_CALLBACKS = false;
protected static final boolean DEFAULT_PARALLEL = false;
protected static final SnapshotFormat DEFAULT_SNAPSHOT_FORMAT = SnapshotFormat.GEMFIRE;
private boolean invokeCallbacks = DEFAULT_INVOKE_CALLBACKS;
private boolean parallel = DEFAULT_PARALLEL;
private final File location;
private final SnapshotFilter filter;
private final SnapshotFormat format;
public SnapshotMetadata(File location) {
this(location, DEFAULT_SNAPSHOT_FORMAT, null);
}
public SnapshotMetadata(File location, SnapshotFormat format) {
this(location, format, null);
}
public SnapshotMetadata(File location, SnapshotFormat format, SnapshotFilter filter) {
Assert.notNull(location, "Location is required");
this.location = location;
this.format = format;
this.filter = filter;
}
public boolean isDirectory() {
return nullSafeIsDirectory(getLocation());
}
public boolean isFile() {
return nullSafeIsFile(getLocation());
}
public File getLocation() {
return this.location;
}
public SnapshotFormat getFormat() {
return Optional.ofNullable(this.format).orElse(DEFAULT_SNAPSHOT_FORMAT);
}
public boolean isFilterPresent() {
return (getFilter() != null);
}
public SnapshotFilter getFilter() {
return this.filter;
}
public void setInvokeCallbacks(boolean invokeCallbacks) {
this.invokeCallbacks = invokeCallbacks;
}
public boolean isInvokeCallbacks() {
return this.invokeCallbacks;
}
public void setParallel(boolean parallel) {
this.parallel = parallel;
}
public boolean isParallel() {
return this.parallel;
}
@Override
public String toString() {
return String.format(
"{ @type = %1$s, location = %2$s, format = %3$s, filter = %4$s, invokeCallbacks = %5$s, parallel = %6$s }",
getClass().getName(), getLocation().getAbsolutePath(), getFormat(), getFilter(),
isInvokeCallbacks(), isParallel());
}
}
/**
* The ArchiveFileFilter class is a Java FileFilter implementation accepting any File that is either
* a JAR file or ZIP file.
*
* @see java.io.File
* @see java.io.FileFilter
*/
protected static final class ArchiveFileFilter implements FileFilter {
protected static final ArchiveFileFilter INSTANCE = new ArchiveFileFilter();
protected static final List ACCEPTED_FILE_EXTENSIONS = Arrays.asList("jar", "zip");
protected static final String FILE_EXTENSION_DOT_SEPARATOR = ".";
protected boolean isJarFile(File file) {
return "jar".equalsIgnoreCase(getFileExtension(file));
}
protected String getFileExtension(File file) {
String fileExtension = "";
if (nullSafeIsFile(file)) {
String pathname = file.getAbsolutePath();
int fileExtensionIndex = pathname.lastIndexOf(FILE_EXTENSION_DOT_SEPARATOR);
fileExtension = (fileExtensionIndex > -1 ? pathname.substring(fileExtensionIndex + 1) : "");
}
return fileExtension.toLowerCase();
}
@Override
public boolean accept(final File pathname) {
return ACCEPTED_FILE_EXTENSIONS.contains(getFileExtension(pathname));
}
}
}