All Downloads are FREE. Search and download functionalities are using the official Maven repository.

org.springframework.data.gemfire.snapshot.SnapshotServiceFactoryBean Maven / Gradle / Ivy

There is a newer version: 2.3.9.RELEASE
Show newest version
/*
 * Copyright 2010-2013 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
 *
 *       http://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 com.gemstone.gemfire.cache.snapshot.SnapshotOptions.SnapshotFormat;
import static org.springframework.data.gemfire.snapshot.SnapshotServiceFactoryBean.SnapshotServiceAdapter;

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.jar.JarFile;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean;
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.util.CollectionUtils;
import org.springframework.util.Assert;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.snapshot.CacheSnapshotService;
import com.gemstone.gemfire.cache.snapshot.RegionSnapshotService;
import com.gemstone.gemfire.cache.snapshot.SnapshotFilter;
import com.gemstone.gemfire.cache.snapshot.SnapshotOptions;

/**
 * The SnapshotServiceFactoryBean class is a Spring FactoryBean used to configure and create an instance
 * of an appropriate 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 com.gemstone.gemfire.cache.snapshot.CacheSnapshotService
 * @see com.gemstone.gemfire.cache.snapshot.RegionSnapshotService
 * @since 1.7.0
 */
@SuppressWarnings("unused")
public class SnapshotServiceFactoryBean implements FactoryBean>,
		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;

	/* (non-Javadoc) */
	@SuppressWarnings("unchecked")
	static  SnapshotMetadata[] nullSafeArray(SnapshotMetadata[] configurations) {
		return (configurations != null ? configurations : EMPTY_ARRAY);
	}

	/* (non-Javadoc) */
	static boolean nullSafeIsDirectory(File file) {
		return (file != null && file.isDirectory());
	}

	/* (non-Javadoc) */
	static boolean nullSafeIsFile(File file) {
		return (file != null && file.isFile());
	}

	/**
	 * Sets a reference to the GemFire Cache for which the snapshot will be taken.
	 *
	 * @param cache the GemFire Cache used to create an instance of CacheSnapshotService.
	 * @throws IllegalArgumentException if the Cache reference is null.
	 * @see com.gemstone.gemfire.cache.Cache
	 * @see #getCache()
	 */
	public void setCache(Cache cache) {
		Assert.notNull(cache, "The GemFire Cache must not be null");
		this.cache = cache;
	}

	/**
	 * Gets a reference to the GemFire Cache for which the snapshot will be taken.
	 *
	 * @return the GemFire Cache used to create an instance of CacheSnapshotService.
	 * @throws IllegalStateException if the Cache argument is null.
	 * @see com.gemstone.gemfire.cache.Cache
	 * @see #setCache(Cache)
	 */
	protected Cache getCache() {
		Assert.state(cache != null, "The GemFire Cache was not properly initialized");
		return cache;
	}

	/**
	 * 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
	 */
	protected SnapshotMetadata[] getExports() {
		return nullSafeArray(exports);
	}

	/**
	 * 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
	 */
	protected SnapshotMetadata[] getImports() {
		return nullSafeArray(imports);
	}

	/**
	 * Sets a reference to the GemFire Region for which the snapshot will be taken.
	 *
	 * @param region the GemFire Region used to create an instance of the RegionSnapshotService.
	 * @see com.gemstone.gemfire.cache.Region
	 * @see #getRegion()
	 */
	public void setRegion(Region region) {
		this.region = region;
	}

	/**
	 * Gets a reference to the GemFire Region for which the snapshot will be taken.
	 *
	 * @return the GemFire Region used to create an instance of the RegionSnapshotService.
	 * @see com.gemstone.gemfire.cache.Region
	 * @see #getRegion()
	 */
	protected Region getRegion() {
		return 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 GemFire Snapshot Service created by this FactoryBean.
	 *
	 * @return the GemFire Snapshot Service created by this FactoryBean.
	 * @throws Exception if the GemFire Snapshot Service failed to be created.
	 * @see SnapshotServiceFactoryBean.SnapshotServiceAdapter
	 */
	@Override
	public SnapshotServiceAdapter getObject() throws Exception {
		return 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
	public Class getObjectType() {
		return (snapshotServiceAdapter != null ? snapshotServiceAdapter.getClass() : SnapshotServiceAdapter.class);
	}

	/**
	 * Determines this this FactoryBean creates single GemFire Snapshot Service instances.
	 *
	 * @return true.
	 */
	@Override
	public boolean isSingleton() {
		return true;
	}

	/**
	 * Constructs and initializes the 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 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 {
		snapshotServiceAdapter = create();

		if (!getSuppressImportOnInit()) {
			snapshotServiceAdapter.doImport(getImports());
		}
	}

	/**
	 * Constructs an appropriate instance of the SnapshotServiceAdapter based on the FactoryBean configuration. If
	 * a Region has not been specified, then a GemFire Snapshot Service for the Cache is constructed, otherwise
	 * the GemFire Snapshot Service for the configured Region is used.
	 *
	 * @return a SnapshotServiceAdapter wrapping the appropriate GemFire Snapshot Service (either Cache or Region)
	 * depending on the FactoryBean configuration.
	 * @see #wrap(CacheSnapshotService)
	 * @see #wrap(RegionSnapshotService)
	 * @see #getRegion()
	 */
	protected SnapshotServiceAdapter create() {
		Region region = getRegion();
		return (region != null ? wrap(region.getSnapshotService()) : wrap(getCache().getSnapshotService()));
	}

	/**
	 * Wraps the GemFire CacheSnapshotService into an appropriate Adapter to uniformly access snapshot operations
	 * on the Cache and Regions alike.
	 *
	 * @param cacheSnapshotService the GemFire CacheSnapshotService to wrap.
	 * @return a SnapshotServiceAdapter wrapping the GemFire CacheSnapshotService.
	 * @see SnapshotServiceFactoryBean.SnapshotServiceAdapter
	 * @see SnapshotServiceFactoryBean.CacheSnapshotServiceAdapter
	 * @see com.gemstone.gemfire.cache.snapshot.CacheSnapshotService
	 */
	protected SnapshotServiceAdapter wrap(CacheSnapshotService cacheSnapshotService) {
		return new CacheSnapshotServiceAdapter(cacheSnapshotService);
	}

	/**
	 * Wraps GemFire's RegionSnapshotService into an appropriate Adapter to uniformly access snapshot operations
	 * on the Cache and Regions alike.
	 *
	 * @param regionSnapshotService the GemFire RegionSnapshotService to wrap.
	 * @return a SnapshotServiceAdapter wrapping the GemFire RegionSnapshotService.
	 * @see SnapshotServiceFactoryBean.SnapshotServiceAdapter
	 * @see SnapshotServiceFactoryBean.RegionSnapshotServiceAdapter
	 * @see com.gemstone.gemfire.cache.snapshot.RegionSnapshotService
	 */
	protected SnapshotServiceAdapter wrap(RegionSnapshotService regionSnapshotService) {
		return new RegionSnapshotServiceAdapter(regionSnapshotService);
	}

	/**
	 * Performs an export of the 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
	public void destroy() throws Exception {
		getObject().doExport(getExports());
	}

	/**
	 * Listens for SnapshotApplicationEvents triggering a GemFire Cache-wide or Region data snapshot import/export
	 * when details of the event match the criteria of this factory's constructed GemFire SnapshotService.
	 *
	 * @param event the SnapshotApplicationEvent triggering a 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
	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 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 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 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 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();

		void doExport(SnapshotMetadata... configurations);

		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 Log log = createLog();

		Log createLog() {
			return LogFactory.getLog(getClass());
		}

		@Override
		public SnapshotOptions createOptions() {
			throw new UnsupportedOperationException("not implemented");
		}

		protected SnapshotOptions createOptions(SnapshotFilter filter) {
			return createOptions().setFilter(filter);
		}

		@Override
		public void doExport(SnapshotMetadata... configurations) {
			for (SnapshotMetadata configuration : nullSafeArray(configurations)) {
				save(configuration.getLocation(), configuration.getFormat(), createOptions(configuration.getFilter()));
			}
		}

		@Override
		public void doImport(SnapshotMetadata... configurations) {
			for (SnapshotMetadata configuration : nullSafeArray(configurations)) {
				load(configuration.getFormat(), createOptions(configuration.getFilter()), handleLocation(configuration));
			}
		}

		protected abstract File[] handleLocation(SnapshotMetadata configuration);

		protected File[] handleDirectoryLocation(File directory) {
			return directory.listFiles(new FileFilter() {
				@Override public boolean accept(File pathname) {
					return 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 t) {
					throw new ImportSnapshotException(String.format(
						"Failed to extract archive (%1$s) to import", file), t);
				}
			}

			return new File[] { file };
		}

		protected boolean exceptionSuppressingClose(Closeable closeable) {
			try {
				closeable.close();
				return true;
			}
			catch (IOException ignore) {
				logDebug(ignore, "Failed to close (%1$s)", closeable);
				return false;
			}
		}

		protected void logDebug(Throwable t, String message, Object... arguments) {
			if (log.isDebugEnabled()) {
				log.debug(String.format(message, arguments), t);
			}
		}

		@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 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 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 t) {
				throw new ImportSnapshotException(String.format(
					"Failed to load snapshots from directory (%1$s) in format (%2$s)",
						directory, format), t);
			}
		}

		@Override
		public void load(SnapshotFormat format, SnapshotOptions options, File... snapshots) {
			try {
				getSnapshotService().load(snapshots, format, options);
			}
			catch (Throwable t) {
				throw new ImportSnapshotException(String.format(
					"Failed to load snapshots (%1$s) in format (%2$s) using options (%3$s)",
						Arrays.toString(snapshots), format, options), t);
			}
		}

		@Override
		public void save(File directory, SnapshotFormat format) {
			try {
				getSnapshotService().save(directory, format);
			}
			catch (Throwable t) {
				throw new ExportSnapshotException(String.format(
					"Failed to save snapshots to directory (%1$s) in format (%2$s)",
						directory, format), t);
			}
		}

		@Override
		public void save(File directory, SnapshotFormat format, SnapshotOptions options) {
			try {
				getSnapshotService().save(directory, format, options);
			}
			catch (Throwable t) {
				throw new ExportSnapshotException(String.format(
					"Failed to save snapshots to directory (%1$s) in format (%2$s) using options (%3$s)",
						directory, format, options), t);
			}
		}
	}

	/**
	 * The RegionSnapshotServiceAdapter is a SnapshotServiceAdapter adapting 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 snapshotService;
		}

		@Override
		public SnapshotOptions createOptions() {
			return getSnapshotService().createOptions();
		}

		@Override
		protected File[] handleLocation(final SnapshotMetadata configuration) {
			return new File[] { configuration.getLocation() };
		}

		@Override
		public void load(File snapshot, SnapshotFormat format) {
			try {
				getSnapshotService().load(snapshot, format);
			}
			catch (Throwable t) {
				throw new ImportSnapshotException(String.format(
					"Failed to load snapshot from file (%1$s) in format (%2$s)",
						snapshot, format), t);
			}
		}

		@Override
		public void load(SnapshotFormat format, SnapshotOptions options, File... snapshots) {
			try {
				for (File snapshot : snapshots) {
					getSnapshotService().load(snapshot, format, options);
				}
			}
			catch (Throwable t) {
				throw new ImportSnapshotException(String.format(
					"Failed to load snapshots (%1$s) in format (%2$s) using options (%3$s)",
						Arrays.toString(snapshots), format, options), t);
			}
		}

		@Override
		public void save(File snapshot, SnapshotFormat format) {
			try {
				getSnapshotService().save(snapshot, format);
			}
			catch (Throwable t) {
				throw new ExportSnapshotException(String.format(
					"Failed to save snapshot to file (%1$s) in format (%2$s)",
						snapshot, format), t);
			}
		}

		@Override
		public void save(File snapshot, SnapshotFormat format, SnapshotOptions options) {
			try {
				getSnapshotService().save(snapshot, format, options);
			}
			catch (Throwable t) {
				throw new ExportSnapshotException(String.format(
					"Failed to save snapshot to file (%1$s) in format (%2$s) using options (%3$s)",
						snapshot, format, options), t);
			}
		}
	}

	/**
	 * The SnapshotMetadata class encapsulates details of the 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 {

		private final File location;

		private final SnapshotFilter filter;

		private final SnapshotFormat format;

		public SnapshotMetadata(File location, SnapshotFormat format) {
			this(location, null, format);
		}

		public SnapshotMetadata(File location, SnapshotFilter filter, SnapshotFormat format) {
			Assert.notNull(location, "Location must not be null");

			this.location = location;
			this.filter = filter;
			this.format = format;
		}

		public boolean isDirectory() {
			return nullSafeIsDirectory(getLocation());
		}

		public boolean isFile() {
			return nullSafeIsFile(getLocation());
		}

		public File getLocation() {
			return location;
		}

		public boolean isFilterPresent() {
			return (getFilter() != null);
		}

		public SnapshotFilter getFilter() {
			return filter;
		}

		public SnapshotFormat getFormat() {
			return (format != null ? format : SnapshotFormat.GEMFIRE);
		}

		@Override
		public String toString() {
			return String.format("{ @type = %1$s, location = %2$s, filter = %2$s, format = %4$s }",
				getClass().getName(), getLocation().getAbsolutePath(), getFilter(), getFormat());
		}
	}

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

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy