SGF-408 - Provide support in the SDG XML namespace to load a pre-defined data set using GemFire Snapshot Service for development and testing purposes.

Refactored the SnapshotApplicationEvent into 2 separate ApplicationEvent classes to handle import and exports.
Refactored the SnapshotServiceFactoryBean class to handle import/export SnapshotApplicationEvents in onApplicationEvent(:SnapshotApplicationEvent).
Added integration tests for the archive file handling capabilities of the SnapshotServiceFactoryBean.SnapshotServiceAdapterSupport class.
Added additional unit tests.
This commit is contained in:
John Blum
2015-08-25 00:53:46 -07:00
parent b47884c88c
commit 35107aa12d
9 changed files with 390 additions and 83 deletions

View File

@@ -0,0 +1,58 @@
/*
* 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;
import static org.springframework.data.gemfire.SnapshotServiceFactoryBean.SnapshotMetadata;
/**
* The ExportSnapshotApplicationEvent class is a Spring ApplicationEvent signaling a GemFire Cache or Region 'import'
* snapshot event.
*
* @author John Blum
* @see org.springframework.data.gemfire.SnapshotApplicationEvent
* @since 1.7.0
*/
@SuppressWarnings("unused")
public class ExportSnapshotApplicationEvent<K, V> extends SnapshotApplicationEvent<K, V> {
/**
* Constructs an instance of ExportSnapshotApplicationEvent initialized with an event source and optional meta-data
* describing the data snapshots to be exported.
*
* @param source the source of the ApplicationEvent.
* @param snapshotMetadata an array of SnapshotMetadata containing details for each export.
* @see org.springframework.data.gemfire.SnapshotServiceFactoryBean.SnapshotMetadata
* @see #ExportSnapshotApplicationEvent(Object, String, SnapshotMetadata[])
*/
public ExportSnapshotApplicationEvent(Object source, SnapshotMetadata<K, V>... snapshotMetadata) {
super(source, snapshotMetadata);
}
/**
* Constructs an instance of ExportSnapshotApplicationEvent initialized with an event source, a pathname
* of the Region from which data is exported along with meta-data describing the details of the snapshot source.
*
* @param source the source of the ApplicationEvent.
* @param regionPath absolute pathname of the Region.
* @param snapshotMetadata an array of SnapshotMetadata containing details for each export.
* @see org.springframework.data.gemfire.SnapshotServiceFactoryBean.SnapshotMetadata
*/
public ExportSnapshotApplicationEvent(Object source, String regionPath, SnapshotMetadata<K, V>... snapshotMetadata) {
super(source, regionPath, snapshotMetadata);
}
}

View File

@@ -0,0 +1,58 @@
/*
* 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;
import static org.springframework.data.gemfire.SnapshotServiceFactoryBean.SnapshotMetadata;
/**
* The ImportSnapshotApplicationEvent class is a Spring ApplicationEvent signaling a GemFire Cache or Region 'export'
* snapshot event.
*
* @author John Blum
* @see org.springframework.data.gemfire.SnapshotApplicationEvent
* @since 1.7.0
*/
@SuppressWarnings("unused")
public class ImportSnapshotApplicationEvent<K, V> extends SnapshotApplicationEvent<K, V> {
/**
* Constructs an instance of ImportSnapshotApplicationEvent initialized with an event source and optional meta-data
* describing the data snapshots to be imported.
*
* @param source the source of the ApplicationEvent.
* @param snapshotMetadata an array of SnapshotMetadata containing details for each import.
* @see org.springframework.data.gemfire.SnapshotServiceFactoryBean.SnapshotMetadata
* @see #ImportSnapshotApplicationEvent(Object, String, SnapshotMetadata[])
*/
public ImportSnapshotApplicationEvent(Object source, SnapshotMetadata<K, V>... snapshotMetadata) {
super(source, snapshotMetadata);
}
/**
* Constructs an instance of ImportSnapshotApplicationEvent initialized with an event source, a pathname
* of the Region in which data is imported along with meta-data describing the details of the snapshot source.
*
* @param source the source of the ApplicationEvent.
* @param regionPath absolute pathname of the Region.
* @param snapshotMetadata an array of SnapshotMetadata containing details for each import/export.
* @see org.springframework.data.gemfire.SnapshotServiceFactoryBean.SnapshotMetadata
*/
public ImportSnapshotApplicationEvent(Object source, String regionPath, SnapshotMetadata<K, V>... snapshotMetadata) {
super(source, regionPath, snapshotMetadata);
}
}

View File

@@ -24,8 +24,8 @@ import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.management.internal.cli.util.spring.StringUtils;
/**
* The SnapshotApplicationEvent class is a Spring ApplicationEvent signaling a GemFire Cache Region(s) snapshot event
* triggering a snapshot to occur.
* The SnapshotApplicationEvent class is a Spring ApplicationEvent signaling a GemFire Cache or Region snapshot event,
* used to trigger a snapshot to occur.
*
* @author John Blum
* @see org.springframework.context.ApplicationEvent
@@ -33,36 +33,36 @@ import com.gemstone.gemfire.management.internal.cli.util.spring.StringUtils;
* @since 1.7.0
*/
@SuppressWarnings("unused")
public class SnapshotApplicationEvent<K, V> extends ApplicationEvent {
public abstract class SnapshotApplicationEvent<K, V> extends ApplicationEvent {
private final SnapshotMetadata<K, V>[] snapshotMetadata;
private final String regionPath;
/**
* Constructs an instance of SnapshotApplicationEvent initialized with an event source along with optional meta-data
* describing the data snapshots to be taken.
* Constructs an instance of SnapshotApplicationEvent initialized with an event source and optional meta-data
* describing the data snapshots to be imported/exported.
*
* @param eventSource the source of the ApplicationEvent.
* @param snapshotMetadata an array of SnapshotMetadata containing details of each export.
* @param source the source of the ApplicationEvent.
* @param snapshotMetadata an array of SnapshotMetadata containing details for each import/export.
* @see org.springframework.data.gemfire.SnapshotServiceFactoryBean.SnapshotMetadata
* @see #SnapshotApplicationEvent(Object, String, SnapshotMetadata[])
*/
public SnapshotApplicationEvent(Object eventSource, SnapshotMetadata<K, V>... snapshotMetadata) {
this(eventSource, null, snapshotMetadata);
public SnapshotApplicationEvent(Object source, SnapshotMetadata<K, V>... snapshotMetadata) {
this(source, null, snapshotMetadata);
}
/**
* Constructs an instance of SnapshotApplicationEvent initialized with an event source and pathname of the Region
* on which the data snapshot(s) will be taken with details provided by the snapshot meta-data.
* Constructs an instance of SnapshotApplicationEvent initialized with an event source, a pathname of the Region
* which data snapshots are imported/exported along with meta-data describing the details of the snapshot source.
*
* @param eventSource the source of the ApplicationEvent.
* @param regionPath the absolute pathname of the Region.
* @param snapshotMetadata an array of SnapshotMetadata containing details of each export.
* @param source the source of the ApplicationEvent.
* @param regionPath absolute pathname of the Region.
* @param snapshotMetadata an array of SnapshotMetadata containing details for each import/export.
* @see org.springframework.data.gemfire.SnapshotServiceFactoryBean.SnapshotMetadata
*/
public SnapshotApplicationEvent(Object eventSource, String regionPath, SnapshotMetadata<K, V>... snapshotMetadata) {
super(eventSource);
public SnapshotApplicationEvent(Object source, String regionPath, SnapshotMetadata<K, V>... snapshotMetadata) {
super(source);
this.snapshotMetadata = snapshotMetadata;
this.regionPath = regionPath;
}

View File

@@ -74,11 +74,11 @@ public class SnapshotServiceFactoryBean<K, V> implements FactoryBean<SnapshotSer
private Region<K, V> region;
private SnapshotServiceAdapter<K, V> snapshotServiceAdapter;
private SnapshotMetadata<K, V>[] exports;
private SnapshotMetadata<K, V>[] imports;
private SnapshotServiceAdapter<K, V> snapshotServiceAdapter;
/* (non-Javadoc) */
@SuppressWarnings("unchecked")
static <K, V> SnapshotMetadata<K, V>[] nullSafeArray(SnapshotMetadata<K, V>[] configurations) {
@@ -231,8 +231,6 @@ public class SnapshotServiceFactoryBean<K, V> implements FactoryBean<SnapshotSer
*/
@Override
@SuppressWarnings("unchecked")
// TODO consider making the "import" on bean initialization asynchronous
// NOTE GemFire may handle asynchronous import and export under the right conditions (need to research)
public void afterPropertiesSet() throws Exception {
snapshotServiceAdapter = create();
snapshotServiceAdapter.doImport(getImports());
@@ -296,22 +294,29 @@ public class SnapshotServiceFactoryBean<K, V> implements FactoryBean<SnapshotSer
}
/**
* Listens for SnapshotApplicationEvents triggering a GemFire Cache-wide or Region data snapshot when
* the details of the event match the criteria of this factory's constructed GemFire SnapshotService.
* 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 export.
* @param event the SnapshotApplicationEvent triggering a GemFire Cache or Region data import/export.
* @see org.springframework.data.gemfire.SnapshotApplicationEvent
* @see org.springframework.data.gemfire.ExportSnapshotApplicationEvent
* @see org.springframework.data.gemfire.ImportSnapshotApplicationEvent
* @see #isMatch(SnapshotApplicationEvent)
* @see #resolveSnapshotMetadata(SnapshotApplicationEvent)
* @see #getObject()
* @see org.springframework.data.gemfire.SnapshotServiceFactoryBean.SnapshotServiceAdapter#doExport(SnapshotMetadata[])
* @see org.springframework.data.gemfire.SnapshotServiceFactoryBean.SnapshotServiceAdapter#doImport(SnapshotMetadata[])
*/
@Override
@SuppressWarnings("unchecked")
public void onApplicationEvent(SnapshotApplicationEvent<K, V> event) {
try {
if (isMatch(event)) {
getObject().doExport(resolveSnapshotMetadata(event));
if (event instanceof ExportSnapshotApplicationEvent) {
getObject().doExport(resolveSnapshotMetadata(event));
}
else {
getObject().doImport(resolveSnapshotMetadata(event));
}
}
}
catch (Exception ignore) {
@@ -335,18 +340,21 @@ public class SnapshotServiceFactoryBean<K, V> implements FactoryBean<SnapshotSer
}
/**
* Resolves the SnapshotMetadata used to perform the GemFire Cache or Region data snapshot (export). If the event
* contains specific SnapshotMetadata, then this is preferred over the factory's own "export" SnapshotMetadata.
* 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 exports.
* @return the resolved SnapshotMetadata, either from the event or this factory's configured imports/exports.
* @see org.springframework.data.gemfire.SnapshotApplicationEvent#getSnapshotMetadata()
* @see #getExports()
* @see #getImports()
*/
protected SnapshotMetadata<K, V>[] resolveSnapshotMetadata(SnapshotApplicationEvent<K, V> event) {
SnapshotMetadata<K, V>[] eventSnapshotMetadata = event.getSnapshotMetadata();
return (!ObjectUtils.isEmpty(eventSnapshotMetadata) ? eventSnapshotMetadata : getExports());
return (!ObjectUtils.isEmpty(eventSnapshotMetadata) ? eventSnapshotMetadata
: (event instanceof ExportSnapshotApplicationEvent ? getExports() : getImports()));
}
/**
@@ -374,6 +382,14 @@ public class SnapshotServiceFactoryBean<K, V> implements FactoryBean<SnapshotSer
}
/**
* SnapshotServiceAdapterSupport is an abstract base class for all SnapshotServiceAdapter implementations
* encapsulating common reusable functionality.
*
* @param <K> the class type of the Cache Region key.
* @param <V> the class type of the Cache Region value.
* @see org.springframework.data.gemfire.SnapshotServiceFactoryBean.SnapshotServiceAdapter
*/
protected static abstract class SnapshotServiceAdapterSupport<K, V> implements SnapshotServiceAdapter<K, V> {
protected final Log log = createLog();
@@ -382,6 +398,11 @@ public class SnapshotServiceFactoryBean<K, V> implements FactoryBean<SnapshotSer
return LogFactory.getLog(getClass());
}
@Override
public SnapshotOptions<K, V> createOptions() {
throw new UnsupportedOperationException("not implemented");
}
protected SnapshotOptions<K, V> createOptions(SnapshotFilter<K, V> filter) {
return createOptions().setFilter(filter);
}
@@ -422,7 +443,7 @@ public class SnapshotServiceFactoryBean<K, V> implements FactoryBean<SnapshotSer
ZipFile zipFile = (ArchiveFileFilter.INSTANCE.isJarFile(file)
? new JarFile(file, false, JarFile.OPEN_READ)
: new ZipFile(file, ZipFile.OPEN_READ));
: new ZipFile(file, ZipFile.OPEN_READ));
for (ZipEntry entry : CollectionUtils.iterable(zipFile.entries())) {
if (!entry.isDirectory()) {
@@ -469,6 +490,26 @@ public class SnapshotServiceFactoryBean<K, V> implements FactoryBean<SnapshotSer
}
}
@Override
public void load(File directory, SnapshotFormat format) {
throw new UnsupportedOperationException("not implemented");
}
@Override
public void load(SnapshotFormat format, SnapshotOptions<K, V> 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<K, V> 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);
@@ -478,6 +519,8 @@ public class SnapshotServiceFactoryBean<K, V> implements FactoryBean<SnapshotSer
/**
* The CacheSnapshotServiceAdapter is a SnapshotServiceAdapter adapting GemFire's CacheSnapshotService.
*
* @see org.springframework.data.gemfire.SnapshotServiceFactoryBean.SnapshotServiceAdapterSupport
*/
protected static class CacheSnapshotServiceAdapter extends SnapshotServiceAdapterSupport<Object, Object> {
@@ -554,6 +597,8 @@ public class SnapshotServiceFactoryBean<K, V> implements FactoryBean<SnapshotSer
/**
* The RegionSnapshotServiceAdapter is a SnapshotServiceAdapter adapting GemFire's RegionSnapshotService.
*
* @see org.springframework.data.gemfire.SnapshotServiceFactoryBean.SnapshotServiceAdapterSupport
*/
protected static class RegionSnapshotServiceAdapter<K, V> extends SnapshotServiceAdapterSupport<K, V> {