Implements SGF-88 - Region Shortcuts; Implements SGF-257 - Strict types in the SDG XSD for Region data-policy and shortcut attributes; Fixes SGF-258 - missing data-policy attribute for Partitioned Regions; Fixes SGF-263 - ineffective application of disk-synchronous attribute setting on Region bean definitions defined with SDG XML namespace.
This commit is contained in:
@@ -15,8 +15,8 @@
|
||||
*/
|
||||
package org.springframework.data.gemfire;
|
||||
|
||||
import org.springframework.data.gemfire.support.RegionShortcutWrapper;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.gemstone.gemfire.cache.DataPolicy;
|
||||
import com.gemstone.gemfire.cache.RegionFactory;
|
||||
@@ -39,6 +39,28 @@ public class LocalRegionFactoryBean<K, V> extends RegionFactoryBean<K, V> {
|
||||
super.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, DataPolicy dataPolicy) {
|
||||
if (dataPolicy == null || DataPolicy.NORMAL.equals(dataPolicy)) {
|
||||
// NOTE this is safe since a LOCAL Scoped NORMAL Region requiring persistence can be satisfied with
|
||||
// PERSISTENT_REPLICATE, per the RegionShortcut.LOCAL_PERSISTENT
|
||||
regionFactory.setDataPolicy(isPersistent() ? DataPolicy.PERSISTENT_REPLICATE : DataPolicy.NORMAL);
|
||||
}
|
||||
else if (DataPolicy.PRELOADED.equals(dataPolicy)) {
|
||||
// NOTE this is safe since a LOCAL Scoped PRELOADED Region requiring persistence can be satisfied with
|
||||
// PERSISTENT_REPLICATE, per the RegionShortcut.LOCAL_PERSISTENT
|
||||
regionFactory.setDataPolicy(isPersistent() ? DataPolicy.PERSISTENT_REPLICATE : DataPolicy.PRELOADED);
|
||||
}
|
||||
else if (DataPolicy.PERSISTENT_REPLICATE.equals(dataPolicy)
|
||||
&& RegionShortcutWrapper.valueOf(getShortcut()).isPersistent()) {
|
||||
regionFactory.setDataPolicy(dataPolicy);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException(String.format("Data Policy '%1$s' is not supported for Local Regions.",
|
||||
dataPolicy));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Resolves the Data Policy used by this "local" GemFire Region (i.e. locally Scoped; Scope.LOCAL) based on the
|
||||
* enumerated value from com.gemstone.gemfire.cache.RegionShortcuts (LOCAL, LOCAL_PERSISTENT, LOCAL_HEAP_LRU,
|
||||
@@ -53,25 +75,14 @@ public class LocalRegionFactoryBean<K, V> extends RegionFactoryBean<K, V> {
|
||||
*/
|
||||
@Override
|
||||
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, String dataPolicy) {
|
||||
DataPolicy resolvedDataPolicy = new DataPolicyConverter().convert(dataPolicy);
|
||||
DataPolicy resolvedDataPolicy = null;
|
||||
|
||||
Assert.isTrue(resolvedDataPolicy != null || !StringUtils.hasText(dataPolicy),
|
||||
String.format("Data Policy '%1$s' is invalid.", dataPolicy));
|
||||
if (dataPolicy != null) {
|
||||
resolvedDataPolicy = new DataPolicyConverter().convert(dataPolicy);
|
||||
Assert.notNull(resolvedDataPolicy, String.format("Data Policy '%1$s' is invalid.", dataPolicy));
|
||||
}
|
||||
|
||||
if (resolvedDataPolicy == null || DataPolicy.NORMAL.equals(resolvedDataPolicy)) {
|
||||
// NOTE this is safe since a LOCAL Scoped NORMAL Region requiring persistence can be satisfied with
|
||||
// PERSISTENT_REPLICATE, per the RegionShortcut.LOCAL_PERSISTENT
|
||||
regionFactory.setDataPolicy(isPersistent() ? DataPolicy.PERSISTENT_REPLICATE : DataPolicy.NORMAL);
|
||||
}
|
||||
else if (DataPolicy.PRELOADED.equals(resolvedDataPolicy)) {
|
||||
// NOTE this is safe since a LOCAL Scoped PRELOADED Region requiring persistence can be satisfied with
|
||||
// PERSISTENT_REPLICATE, per the RegionShortcut.LOCAL_PERSISTENT
|
||||
regionFactory.setDataPolicy(isPersistent() ? DataPolicy.PERSISTENT_REPLICATE : DataPolicy.PRELOADED);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException(String.format("Data Policy '%1$s' is not supported in Local Regions.",
|
||||
dataPolicy));
|
||||
}
|
||||
resolveDataPolicy(regionFactory, persistent, resolvedDataPolicy);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -28,32 +28,38 @@ import com.gemstone.gemfire.cache.RegionFactory;
|
||||
public class PartitionedRegionFactoryBean<K, V> extends RegionFactoryBean<K, V> {
|
||||
|
||||
@Override
|
||||
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, String dataPolicy) {
|
||||
if (dataPolicy != null) {
|
||||
DataPolicy resolvedDataPolicy = new DataPolicyConverter().convert(dataPolicy);
|
||||
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, DataPolicy dataPolicy) {
|
||||
// First, verify the GemFire version is 6.5 or Higher when Persistence is specified...
|
||||
Assert.isTrue(!DataPolicy.PERSISTENT_PARTITION.equals(dataPolicy) || GemfireUtils.isGemfireVersion65OrAbove(),
|
||||
String.format("Persistent PARTITION Regions can only be used from GemFire 6.5 onwards; current version is [%1$s].",
|
||||
CacheFactory.getVersion()));
|
||||
|
||||
Assert.notNull(resolvedDataPolicy, String.format("Data Policy '%1$s' is invalid.", dataPolicy));
|
||||
|
||||
// Validate that the user-defined Data Policy matches the appropriate Spring GemFire XML namespace
|
||||
// configuration meta-data element for Region (i.e. <gfe:partitioned-region .../>)!
|
||||
Assert.isTrue(resolvedDataPolicy.withPartitioning(), String.format(
|
||||
"Data Policy '%1$s' is not supported in Partitioned Regions.", resolvedDataPolicy));
|
||||
|
||||
// Validate that the data-policy and persistent attributes are compatible when specified!
|
||||
assertDataPolicyAndPersistentAttributesAreCompatible(resolvedDataPolicy);
|
||||
|
||||
regionFactory.setDataPolicy(resolvedDataPolicy);
|
||||
}
|
||||
else if (isPersistent()) {
|
||||
// first, check the presence of GemFire 6.5 or Higher
|
||||
Assert.isTrue(GemfireUtils.isGemfireVersion65OrAbove(), String.format(
|
||||
"Can define Persistent Partitioned Regions only from GemFire 6.5 onwards; current version is [%1$s]",
|
||||
CacheFactory.getVersion()));
|
||||
regionFactory.setDataPolicy(DataPolicy.PERSISTENT_PARTITION);
|
||||
if (dataPolicy == null) {
|
||||
dataPolicy = (isPersistent() ? DataPolicy.PERSISTENT_PARTITION : DataPolicy.PARTITION);
|
||||
}
|
||||
else {
|
||||
regionFactory.setDataPolicy(DataPolicy.PARTITION);
|
||||
// Validate that the user-defined Data Policy matches the appropriate Spring GemFire XML namespace
|
||||
// configuration meta-data element for Region (i.e. <gfe:partitioned-region .../>)!
|
||||
Assert.isTrue(dataPolicy.withPartitioning(), String.format(
|
||||
"Data Policy '%1$s' is not supported in Partitioned Regions.", dataPolicy));
|
||||
}
|
||||
|
||||
// Validate the data-policy and persistent attributes are compatible when specified!
|
||||
assertDataPolicyAndPersistentAttributesAreCompatible(dataPolicy);
|
||||
|
||||
regionFactory.setDataPolicy(dataPolicy);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, String dataPolicy) {
|
||||
DataPolicy resolvedDataPolicy = null;
|
||||
|
||||
if (dataPolicy != null) {
|
||||
resolvedDataPolicy = new DataPolicyConverter().convert(dataPolicy);
|
||||
Assert.notNull(resolvedDataPolicy, String.format("Data Policy '%1$s' is invalid.", dataPolicy));
|
||||
}
|
||||
|
||||
resolveDataPolicy(regionFactory, persistent, resolvedDataPolicy);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.context.SmartLifecycle;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.support.RegionShortcutWrapper;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
@@ -35,12 +36,16 @@ import com.gemstone.gemfire.cache.CacheLoader;
|
||||
import com.gemstone.gemfire.cache.CacheWriter;
|
||||
import com.gemstone.gemfire.cache.DataPolicy;
|
||||
import com.gemstone.gemfire.cache.GemFireCache;
|
||||
import com.gemstone.gemfire.cache.PartitionAttributes;
|
||||
import com.gemstone.gemfire.cache.PartitionAttributesFactory;
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
import com.gemstone.gemfire.cache.RegionAttributes;
|
||||
import com.gemstone.gemfire.cache.RegionFactory;
|
||||
import com.gemstone.gemfire.cache.RegionShortcut;
|
||||
import com.gemstone.gemfire.cache.Scope;
|
||||
import com.gemstone.gemfire.cache.asyncqueue.AsyncEventQueue;
|
||||
import com.gemstone.gemfire.cache.wan.GatewaySender;
|
||||
import com.gemstone.gemfire.internal.cache.UserSpecifiedRegionAttributes;
|
||||
|
||||
/**
|
||||
* Base class for FactoryBeans used to create GemFire {@link Region}s. Will try
|
||||
@@ -56,6 +61,7 @@ import com.gemstone.gemfire.cache.wan.GatewaySender;
|
||||
* @author David Turanski
|
||||
* @author John Blum
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> implements DisposableBean, SmartLifecycle {
|
||||
|
||||
protected final Log log = LogFactory.getLog(getClass());
|
||||
@@ -74,16 +80,19 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
|
||||
|
||||
private CacheWriter<K, V> cacheWriter;
|
||||
|
||||
private DataPolicy dataPolicy;
|
||||
|
||||
private Object[] asyncEventQueues;
|
||||
private Object[] gatewaySenders;
|
||||
|
||||
private RegionAttributes<K, V> attributes;
|
||||
|
||||
private RegionShortcut shortcut;
|
||||
|
||||
private Resource snapshot;
|
||||
|
||||
private Scope scope;
|
||||
|
||||
private String dataPolicy;
|
||||
private String diskStoreName;
|
||||
private String hubId;
|
||||
|
||||
@@ -94,27 +103,17 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("deprecation")
|
||||
protected Region<K, V> lookupFallback(GemFireCache gemfireCache, String regionName) throws Exception {
|
||||
Assert.isTrue(gemfireCache instanceof Cache, "Unable to create Regions from " + gemfireCache);
|
||||
|
||||
Cache cache = (Cache) gemfireCache;
|
||||
RegionFactory<K, V> regionFactory;
|
||||
|
||||
if (attributes != null) {
|
||||
// TODO refactor... AttributesFactory extended by the SDG RegionAttributesFactoryBean and used by all
|
||||
// RegionFactoryBeans subclasses calls AttributesFactory.validateAttributes(..) before the RegionAttributes
|
||||
// are created in the AttributesFactory.create() method, which is called by
|
||||
// RegionAttributesFactoryBean.afterPropertiesSet() method.
|
||||
AttributesFactory.validateAttributes(attributes);
|
||||
regionFactory = cache.createRegionFactory(attributes);
|
||||
}
|
||||
else {
|
||||
regionFactory = cache.createRegionFactory();
|
||||
}
|
||||
RegionFactory<K, V> regionFactory = createRegionFactory(cache);
|
||||
|
||||
if (hubId != null) {
|
||||
enableGateway = (enableGateway == null || enableGateway);
|
||||
Assert.isTrue(enableGateway, "hubId requires the enableGateway property to be true");
|
||||
Assert.isTrue(enableGateway, "The 'hubId' requires the 'enableGateway' property to be true");
|
||||
regionFactory.setGatewayHubId(hubId);
|
||||
}
|
||||
|
||||
@@ -154,12 +153,12 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
|
||||
regionFactory.setCacheWriter(cacheWriter);
|
||||
}
|
||||
|
||||
resolveDataPolicy(regionFactory, persistent, dataPolicy);
|
||||
|
||||
if (diskStoreName != null) {
|
||||
regionFactory.setDiskStoreName(diskStoreName);
|
||||
}
|
||||
|
||||
resolveDataPolicy(regionFactory, persistent, dataPolicy);
|
||||
|
||||
if (scope != null) {
|
||||
regionFactory.setScope(scope);
|
||||
}
|
||||
@@ -169,8 +168,7 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
|
||||
"Lock Grantor only applies to a global scoped region.");
|
||||
}
|
||||
|
||||
// get underlying AttributesFactory
|
||||
postProcess(findAttributesFactory(regionFactory));
|
||||
postProcess(regionFactory);
|
||||
|
||||
Region<K, V> region = (getParent() != null ? regionFactory.createSubregion(getParent(), regionName)
|
||||
: regionFactory.create(regionName));
|
||||
@@ -196,12 +194,279 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
|
||||
return region;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that the settings for Data Policy and the 'persistent' attribute in <gfe:*-region/> elements
|
||||
* are compatible.
|
||||
* <p/>
|
||||
* @param resolvedDataPolicy the GemFire Data Policy resolved form the Spring GemFire XML namespace configuration
|
||||
* meta-data.
|
||||
* @see #isPersistent()
|
||||
* @see #isNotPersistent()
|
||||
* @see com.gemstone.gemfire.cache.DataPolicy
|
||||
*/
|
||||
protected void assertDataPolicyAndPersistentAttributesAreCompatible(DataPolicy resolvedDataPolicy) {
|
||||
if (resolvedDataPolicy.withPersistence()) {
|
||||
Assert.isTrue(isPersistentUnspecified() || isPersistent(), String.format(
|
||||
"Data Policy '%1$s' is invalid when persistent is false.", resolvedDataPolicy));
|
||||
}
|
||||
else {
|
||||
// NOTE otherwise, the Data Policy is not persistent, so...
|
||||
Assert.isTrue(isPersistentUnspecified() || isNotPersistent(), String.format(
|
||||
"Data Policy '%1$s' is invalid when persistent is true.", resolvedDataPolicy));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines whether the user explicitly set the 'persistent' attribute or not.
|
||||
* <p/>
|
||||
* @return a boolean value indicating whether the user explicitly set the 'persistent' attribute to true or false.
|
||||
* @see #isPersistent()
|
||||
* @see #isNotPersistent()
|
||||
*/
|
||||
protected boolean isPersistentUnspecified() {
|
||||
return (persistent == null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true when the user explicitly specified a value for the persistent attribute and it is true. If the
|
||||
* persistent attribute was not explicitly specified, then the persistence setting is implicitly undefined
|
||||
* and will be determined by the Data Policy.
|
||||
* <p/>
|
||||
* @return true when the user specified an explicit value for the persistent attribute and it is true;
|
||||
* false otherwise.
|
||||
* @see #isNotPersistent()
|
||||
* @see #isPersistentUnspecified()
|
||||
*/
|
||||
protected boolean isPersistent() {
|
||||
return Boolean.TRUE.equals(persistent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true when the user explicitly specified a value for the persistent attribute and it is false. If the
|
||||
* persistent attribute was not explicitly specified, then the persistence setting is implicitly undefined
|
||||
* and will be determined by the Data Policy.
|
||||
* <p/>
|
||||
* @return true when the user specified an explicit value for the persistent attribute and it is false;
|
||||
* false otherwise.
|
||||
* @see #isPersistent()
|
||||
* @see #isPersistentUnspecified()
|
||||
*/
|
||||
protected boolean isNotPersistent() {
|
||||
return Boolean.FALSE.equals(persistent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates an instance of RegionFactory using the given Cache instance used to configure and construct the Region
|
||||
* created by this FactoryBean.
|
||||
* <p/>
|
||||
* @param cache the GemFire Cache instance.
|
||||
* @return a RegionFactory used to configure and construct the Region created by this FactoryBean.
|
||||
* @see com.gemstone.gemfire.cache.Cache#createRegionFactory()
|
||||
* @see com.gemstone.gemfire.cache.Cache#createRegionFactory(com.gemstone.gemfire.cache.RegionAttributes)
|
||||
* @see com.gemstone.gemfire.cache.Cache#createRegionFactory(com.gemstone.gemfire.cache.RegionShortcut)
|
||||
* @see com.gemstone.gemfire.cache.RegionFactory
|
||||
*/
|
||||
protected RegionFactory<K, V> createRegionFactory(final Cache cache) {
|
||||
if (shortcut != null) {
|
||||
RegionFactory<K, V> regionFactory = mergeRegionAttributes(
|
||||
cache.<K, V>createRegionFactory(shortcut), attributes);
|
||||
setDataPolicy(getDataPolicy(regionFactory));
|
||||
return regionFactory;
|
||||
}
|
||||
else if (attributes != null) {
|
||||
return cache.createRegionFactory(attributes);
|
||||
}
|
||||
else {
|
||||
return cache.createRegionFactory();
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc) - this method is meant strictly to be overridden for testing purposes!
|
||||
* @see com.gemstone.gemfire.cache.RegionFactory#attrsFactory
|
||||
* @see com.gemstone.gemfire.cache.AttributesFactory#regionAttributes
|
||||
* @see com.gemstone.gemfire.cache.RegionAttributes#getDataPolicy
|
||||
* @see com.gemstone.gemfire.cache.DataPolicy
|
||||
*/
|
||||
@SuppressWarnings({ "deprecation", "unchecked"})
|
||||
DataPolicy getDataPolicy(final RegionFactory regionFactory) {
|
||||
// NOTE cannot pass RegionAttributes.class as the "targetType" on the second invocation of getFieldValue(..)
|
||||
// since the "regionAttributes" field is naively of the implementation class type rather than the interface
|
||||
// type... so much for programming to interfaces.
|
||||
return ((RegionAttributes) getFieldValue(getFieldValue(regionFactory, "attrsFactory", AttributesFactory.class),
|
||||
"regionAttributes", null)).getDataPolicy();
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
private <T> T getFieldValue(final Object source, final String fieldName, final Class<T> targetType) {
|
||||
Field field = ReflectionUtils.findField(source.getClass(), fieldName, targetType);
|
||||
ReflectionUtils.makeAccessible(field);
|
||||
return (T) ReflectionUtils.getField(field, source);
|
||||
}
|
||||
|
||||
/**
|
||||
* Intelligently merges the given RegionAttributes with the configuration setting of the RegionFactory. This method
|
||||
* is used to merge the RegionAttributes and PartitionAttributes with the RegionFactory that is created when the
|
||||
* user specified a RegionShortcut. This method gets called by the createRegionFactory method depending upon
|
||||
* the value passed to the Cache.createRegionFactory() method (i.e. whether there was a RegionShortcut specified
|
||||
* or not).
|
||||
* <p/>
|
||||
* @param <K> the Class type fo the Region key.
|
||||
* @param <V> the Class type of the Region value.
|
||||
* @param regionFactory the GemFire RegionFactory used to configure and create the Region that is the product
|
||||
* of this RegionFactoryBean.
|
||||
* @param regionAttributes the RegionAttributes containing the Region configuration settings to merge to the
|
||||
* RegionFactory.
|
||||
* @return the RegionFactory with the configuration settings of the RegionAttributes merged.
|
||||
* @see #hasUserSpecifiedEvictionAttributes(com.gemstone.gemfire.cache.RegionAttributes)
|
||||
* @see #validateRegionAttributes(com.gemstone.gemfire.cache.RegionAttributes)
|
||||
* @see com.gemstone.gemfire.cache.RegionAttributes
|
||||
* @see com.gemstone.gemfire.cache.RegionFactory
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <K, V> RegionFactory<K, V> mergeRegionAttributes(final RegionFactory<K, V> regionFactory,
|
||||
final RegionAttributes<K, V> regionAttributes) {
|
||||
|
||||
if (regionAttributes != null) {
|
||||
// NOTE this validation may not be strictly required depending on how the RegionAttributes were "created",
|
||||
// but...
|
||||
validateRegionAttributes(regionAttributes);
|
||||
|
||||
regionFactory.setCloningEnabled(regionAttributes.getCloningEnabled());
|
||||
regionFactory.setConcurrencyChecksEnabled(regionAttributes.getConcurrencyChecksEnabled());
|
||||
regionFactory.setConcurrencyLevel(regionAttributes.getConcurrencyLevel());
|
||||
regionFactory.setCustomEntryIdleTimeout(regionAttributes.getCustomEntryIdleTimeout());
|
||||
regionFactory.setCustomEntryTimeToLive(regionAttributes.getCustomEntryTimeToLive());
|
||||
regionFactory.setDiskSynchronous(regionAttributes.isDiskSynchronous());
|
||||
regionFactory.setEnableAsyncConflation(regionAttributes.getEnableAsyncConflation());
|
||||
regionFactory.setEnableSubscriptionConflation(regionAttributes.getEnableSubscriptionConflation());
|
||||
regionFactory.setEntryIdleTimeout(regionAttributes.getEntryIdleTimeout());
|
||||
regionFactory.setEntryTimeToLive(regionAttributes.getEntryTimeToLive());
|
||||
|
||||
// NOTE EvictionAttributes are created by certain RegionShortcuts; need the null check!
|
||||
if (hasUserSpecifiedEvictionAttributes(regionAttributes)) {
|
||||
regionFactory.setEvictionAttributes(regionAttributes.getEvictionAttributes());
|
||||
}
|
||||
|
||||
regionFactory.setIgnoreJTA(regionAttributes.getIgnoreJTA());
|
||||
regionFactory.setIndexMaintenanceSynchronous(regionAttributes.getIndexMaintenanceSynchronous());
|
||||
regionFactory.setInitialCapacity(regionAttributes.getInitialCapacity());
|
||||
regionFactory.setKeyConstraint(regionAttributes.getKeyConstraint());
|
||||
regionFactory.setLoadFactor(regionAttributes.getLoadFactor());
|
||||
regionFactory.setLockGrantor(regionAttributes.isLockGrantor());
|
||||
regionFactory.setMembershipAttributes(regionAttributes.getMembershipAttributes());
|
||||
regionFactory.setMulticastEnabled(regionAttributes.getMulticastEnabled());
|
||||
mergePartitionAttributes(regionFactory, regionAttributes);
|
||||
regionFactory.setPoolName(regionAttributes.getPoolName());
|
||||
regionFactory.setRegionIdleTimeout(regionAttributes.getRegionIdleTimeout());
|
||||
regionFactory.setRegionTimeToLive(regionAttributes.getRegionTimeToLive());
|
||||
regionFactory.setStatisticsEnabled(regionAttributes.getStatisticsEnabled());
|
||||
regionFactory.setSubscriptionAttributes(regionAttributes.getSubscriptionAttributes());
|
||||
regionFactory.setValueConstraint(regionAttributes.getValueConstraint());
|
||||
}
|
||||
|
||||
return regionFactory;
|
||||
}
|
||||
|
||||
protected <K, V> void mergePartitionAttributes(final RegionFactory<K, V> regionFactory, final RegionAttributes<K, V> regionAttributes) {
|
||||
// NOTE PartitionAttributes are created by certain RegionShortcuts; need the null check since RegionAttributes
|
||||
// can technically return null!
|
||||
// NOTE most likely, the PartitionAttributes will never be null since the PartitionRegionFactoryBean always
|
||||
// sets a PartitionAttributesFactoryBean BeanBuilder on the RegionAttributesFactoryBean "partitionAttributes"
|
||||
// property.
|
||||
if (regionAttributes.getPartitionAttributes() != null) {
|
||||
PartitionAttributes partitionAttributes = regionAttributes.getPartitionAttributes();
|
||||
PartitionAttributesFactory partitionAttributesFactory = new PartitionAttributesFactory(partitionAttributes);
|
||||
RegionShortcutWrapper shortcutWrapper = RegionShortcutWrapper.valueOf(shortcut);
|
||||
|
||||
// NOTE however, since the default value of redundancy is 0, we need to account for 'redundant'
|
||||
// RegionShortcut types, which specify a redundancy of 1.
|
||||
if (shortcutWrapper.isRedundant() && partitionAttributes.getRedundantCopies() == 0) {
|
||||
partitionAttributesFactory.setRedundantCopies(1);
|
||||
}
|
||||
|
||||
// NOTE and, since the default value of localMaxMemory is based on the system memory, we need to account for
|
||||
// 'proxy' RegionShortcut types, which specify a local max memory of 0.
|
||||
if (shortcutWrapper.isProxy()) {
|
||||
partitionAttributesFactory.setLocalMaxMemory(0);
|
||||
}
|
||||
|
||||
// NOTE internally, RegionFactory.setPartitionAttributes handles merging the PartitionAttributes, hooray!
|
||||
regionFactory.setPartitionAttributes(partitionAttributesFactory.create());
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc) - this method is meant strictly to be overridden for testing purposes!
|
||||
* NOTE unfortunately, must resort to using a GemFire internal class, ugh!
|
||||
* @see com.gemstone.gemfire.internal.cache.UserSpecifiedRegionAttributes#hasEvictionAttributes
|
||||
*/
|
||||
boolean hasUserSpecifiedEvictionAttributes(final RegionAttributes regionAttributes) {
|
||||
return (regionAttributes instanceof UserSpecifiedRegionAttributes
|
||||
&& ((UserSpecifiedRegionAttributes) regionAttributes).hasEvictionAttributes());
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc) - this method is meant strictly to be overridden for testing purposes!
|
||||
* @see com.gemstone.gemfire.cache.AttributesFactory#validateAttributes(:RegionAttributes)
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
void validateRegionAttributes(final RegionAttributes regionAttributes) {
|
||||
AttributesFactory.validateAttributes(regionAttributes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-process the RegionFactory used to create the GemFire Region for this factory bean during the initialization
|
||||
* process. The RegionFactory is already configured and initialized by the factory bean before this method
|
||||
* is invoked.
|
||||
* <p/>
|
||||
* @param regionFactory the GemFire RegionFactory used to create the Region for post-processing.
|
||||
* @see com.gemstone.gemfire.cache.RegionFactory
|
||||
*/
|
||||
protected void postProcess(RegionFactory<K, V> regionFactory) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-process the Region for this factory bean during the initialization process. The Region is
|
||||
* already configured and initialized by the factory bean before this method is invoked.
|
||||
* <p/>
|
||||
* @param region the GemFire Region to post-process.
|
||||
* @see com.gemstone.gemfire.cache.Region
|
||||
*/
|
||||
protected void postProcess(Region<K, V> region) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates and sets the Data Policy on the RegionFactory used to create and configure the Region from this
|
||||
* FactoryBean.
|
||||
* <p/>
|
||||
* @param regionFactory the RegionFactory used by this FactoryBean to create and configure the Region.
|
||||
* @param persistent a boolean value indicating whether the Region should be persistent and persist it's
|
||||
* data to disk.
|
||||
* @param dataPolicy the configured Data Policy for the Region.
|
||||
* @see #resolveDataPolicy(com.gemstone.gemfire.cache.RegionFactory, Boolean, String)
|
||||
* @see com.gemstone.gemfire.cache.DataPolicy
|
||||
* @see com.gemstone.gemfire.cache.RegionFactory
|
||||
*/
|
||||
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, DataPolicy dataPolicy) {
|
||||
if (dataPolicy != null) {
|
||||
assertDataPolicyAndPersistentAttributesAreCompatible(dataPolicy);
|
||||
regionFactory.setDataPolicy(dataPolicy);
|
||||
}
|
||||
else {
|
||||
resolveDataPolicy(regionFactory, persistent, (String) null);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the configured Data Policy and may override it, taking into account the 'persistent' attribute
|
||||
* and constraints for the Region type.
|
||||
* <p/>
|
||||
* @param regionFactory the GemFire RegionFactory used to created the Local Region.
|
||||
* @param persistent a boolean value indicating whether the Local Region should persist it's data.
|
||||
* @param regionFactory the GemFire RegionFactory used to create the desired Region.
|
||||
* @param persistent a boolean value indicating whether the Region should persist it's data to disk.
|
||||
* @param dataPolicy requested Data Policy as set by the user in the Spring GemFire configuration meta-data.
|
||||
* @see com.gemstone.gemfire.cache.DataPolicy
|
||||
* @see com.gemstone.gemfire.cache.RegionFactory
|
||||
@@ -220,40 +485,6 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private AttributesFactory<K, V> findAttributesFactory(RegionFactory<K, V> regionFactory) {
|
||||
Field attrsFactoryField = ReflectionUtils.findField(RegionFactory.class, "attrsFactory",
|
||||
AttributesFactory.class);
|
||||
ReflectionUtils.makeAccessible(attrsFactoryField);
|
||||
return (AttributesFactory<K, V>) ReflectionUtils.getField(attrsFactoryField, regionFactory);
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-process the attribute factory object used for configuring the region
|
||||
* of this factory bean during the initialization process. The object is
|
||||
* already initialized and configured by the factory bean before this method
|
||||
* is invoked.
|
||||
*
|
||||
* @param attributesFactory attribute factory
|
||||
* @deprecated as of GemFire 6.5, the use of {@link AttributesFactory} has
|
||||
* been deprecated
|
||||
*/
|
||||
@Deprecated
|
||||
@SuppressWarnings("unused")
|
||||
protected void postProcess(AttributesFactory<K, V> attributesFactory) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Post-process the region object for this factory bean during the
|
||||
* initialization process. The object is already initialized and configured
|
||||
* by the factory bean before this method is invoked.
|
||||
*
|
||||
* @param region
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
protected void postProcess(Region<K, V> region) {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
if (getRegion() != null) {
|
||||
@@ -274,9 +505,9 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param asyncEventQueues defined as Object for backward compatibility with
|
||||
* Gemfire 6
|
||||
* The list of AsyncEventQueues to use with this Region.
|
||||
* <p/>
|
||||
* @param asyncEventQueues defined as Object for backwards compatibility with Gemfire 6.
|
||||
*/
|
||||
public void setAsyncEventQueues(Object[] asyncEventQueues) {
|
||||
this.asyncEventQueues = asyncEventQueues;
|
||||
@@ -293,14 +524,6 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
|
||||
this.attributes = attributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the region referred by this factory bean, will be
|
||||
* closed on shutdown (default true).
|
||||
*/
|
||||
public void setClose(boolean close) {
|
||||
this.close = close;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cache listeners used for the region used by this factory. Used
|
||||
* only when a new region is created.Overrides the settings specified
|
||||
@@ -334,6 +557,14 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
|
||||
this.cacheWriter = cacheWriter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the region referred by this factory bean, will be
|
||||
* closed on shutdown (default true).
|
||||
*/
|
||||
public void setClose(boolean close) {
|
||||
this.close = close;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the region referred by this factory bean, will be
|
||||
* destroyed on shutdown (default false).
|
||||
@@ -343,17 +574,30 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the dataPolicy as a String. Required to support property
|
||||
* placeholders
|
||||
* @param dataPolicyName the dataPolicy name (NORMAL, PRELOADED, etc)
|
||||
* Sets the DataPolicy of the Region.
|
||||
* <p/>
|
||||
* @param dataPolicy the GemFire DataPolicy to use when configuring the Region.
|
||||
* @since 1.4.0
|
||||
*/
|
||||
public void setDataPolicy(String dataPolicyName) {
|
||||
this.dataPolicy = dataPolicyName;
|
||||
public void setDataPolicy(DataPolicy dataPolicy) {
|
||||
this.dataPolicy = dataPolicy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of disk store to use for overflow and persistence
|
||||
* @param diskStoreName
|
||||
* Sets the DataPolicy of the Region as a String.
|
||||
* <p/>
|
||||
* @param dataPolicyName the name of the DataPolicy (e.g. REPLICATE, PARTITION)
|
||||
* @see #setDataPolicy(com.gemstone.gemfire.cache.DataPolicy)
|
||||
* @deprecated as of 1.4.0, use setDataPolicy(:DataPolicy) instead.
|
||||
*/
|
||||
public void setDataPolicy(String dataPolicyName) {
|
||||
this.dataPolicy = new DataPolicyConverter().convert(dataPolicyName);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of Disk Store used for either overflow or persistence, or both.
|
||||
* <p/>
|
||||
* @param diskStoreName the name of the Disk Store bean in context used for overflow/persistence.
|
||||
*/
|
||||
public void setDiskStoreName(String diskStoreName) {
|
||||
this.diskStoreName = diskStoreName;
|
||||
@@ -376,7 +620,7 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
|
||||
this.hubId = hubId;
|
||||
}
|
||||
|
||||
public void setPersistent(boolean persistent) {
|
||||
public void setPersistent(Boolean persistent) {
|
||||
this.persistent = persistent;
|
||||
}
|
||||
|
||||
@@ -391,6 +635,24 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*/
|
||||
protected final RegionShortcut getShortcut() {
|
||||
return shortcut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Configures the Region with a RegionShortcut.
|
||||
* <p/>
|
||||
* @param shortcut the RegionShortcut used to configure pre-defined default for the Region created
|
||||
* by this FactoryBean.
|
||||
* @see com.gemstone.gemfire.cache.RegionShortcut
|
||||
*/
|
||||
public void setShortcut(RegionShortcut shortcut) {
|
||||
this.shortcut = shortcut;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the snapshots used for loading a newly <i>created</i> region. That
|
||||
* is, the snapshot will be used <i>only</i> when a new region is created -
|
||||
@@ -403,57 +665,8 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
|
||||
this.snapshot = snapshot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that the settings for Data Policy and the 'persistent' attribute in <gfe:*-region/> elements
|
||||
* are compatible.
|
||||
* <p/>
|
||||
* @param resolvedDataPolicy the GemFire Data Policy resolved form the Spring GemFire XML namespace configuration
|
||||
* meta-data.
|
||||
* @see #isPersistent()
|
||||
* @see #isNotPersistent()
|
||||
* @see com.gemstone.gemfire.cache.DataPolicy
|
||||
*/
|
||||
protected void assertDataPolicyAndPersistentAttributesAreCompatible(final DataPolicy resolvedDataPolicy) {
|
||||
final boolean persistentNotSpecified = (this.persistent == null);
|
||||
|
||||
if (resolvedDataPolicy.withPersistence()) {
|
||||
Assert.isTrue(persistentNotSpecified || isPersistent(), String.format(
|
||||
"Data Policy '%1$s' is invalid when persistent is false.", resolvedDataPolicy));
|
||||
}
|
||||
else {
|
||||
// NOTE otherwise, the Data Policy is with persistence, so...
|
||||
Assert.isTrue(persistentNotSpecified || isNotPersistent(), String.format(
|
||||
"Data Policy '%1$s' is invalid when persistent is true.", resolvedDataPolicy));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true when the user explicitly specified a value for the persistent attribute and it is true. If the
|
||||
* persistent attribute was not explicitly specified, then the persistence setting is implicitly undefined
|
||||
* and will be determined by the Data Policy.
|
||||
* <p/>
|
||||
* @return true when the user specified an explicit value for the persistent attribute and it is true;
|
||||
* false otherwise.
|
||||
* @see #isNotPersistent()
|
||||
*/
|
||||
protected boolean isPersistent() {
|
||||
return Boolean.TRUE.equals(persistent);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true when the user explicitly specified a value for the persistent attribute and it is false. If the
|
||||
* persistent attribute was not explicitly specified, then the persistence setting is implicitly undefined
|
||||
* and will be determined by the Data Policy.
|
||||
* <p/>
|
||||
* @return true when the user specified an explicit value for the persistent attribute and it is false;
|
||||
* false otherwise.
|
||||
* @see #isPersistent()
|
||||
*/
|
||||
protected boolean isNotPersistent() {
|
||||
return Boolean.FALSE.equals(persistent);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.Lifecycle#start()
|
||||
*/
|
||||
@Override
|
||||
@@ -461,9 +674,9 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
|
||||
if (!ObjectUtils.isEmpty(gatewaySenders)) {
|
||||
synchronized (gatewaySenders) {
|
||||
for (Object obj : gatewaySenders) {
|
||||
GatewaySender gws = (GatewaySender) obj;
|
||||
if (!(gws.isManualStart() || gws.isRunning())) {
|
||||
gws.start();
|
||||
GatewaySender gatewaySender = (GatewaySender) obj;
|
||||
if (!(gatewaySender.isManualStart() || gatewaySender.isRunning())) {
|
||||
gatewaySender.start();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -471,22 +684,25 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
|
||||
this.running = true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.Lifecycle#stop()
|
||||
*/
|
||||
@Override
|
||||
public void stop() {
|
||||
if (!ObjectUtils.isEmpty(gatewaySenders)) {
|
||||
synchronized (gatewaySenders) {
|
||||
for (Object obj : gatewaySenders) {
|
||||
((GatewaySender) obj).stop();
|
||||
for (Object gatewaySender : gatewaySenders) {
|
||||
((GatewaySender) gatewaySender).stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.running = false;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.Lifecycle#isRunning()
|
||||
*/
|
||||
@Override
|
||||
@@ -494,7 +710,8 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
|
||||
return this.running;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.Phased#getPhase()
|
||||
*/
|
||||
@Override
|
||||
@@ -502,7 +719,8 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.SmartLifecycle#isAutoStartup()
|
||||
*/
|
||||
@Override
|
||||
@@ -510,7 +728,8 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
|
||||
return this.autoStartup;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
* @see org.springframework.context.SmartLifecycle#stop(java.lang.Runnable)
|
||||
*/
|
||||
@Override
|
||||
|
||||
@@ -27,30 +27,36 @@ import com.gemstone.gemfire.cache.RegionFactory;
|
||||
public class ReplicatedRegionFactoryBean<K, V> extends RegionFactoryBean<K, V> {
|
||||
|
||||
@Override
|
||||
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, String dataPolicy) {
|
||||
if (dataPolicy != null) {
|
||||
DataPolicy resolvedDataPolicy = new DataPolicyConverter().convert(dataPolicy);
|
||||
|
||||
Assert.notNull(resolvedDataPolicy, String.format("Data Policy '%1$s' is invalid.", dataPolicy));
|
||||
|
||||
if (DataPolicy.EMPTY.equals(resolvedDataPolicy)) {
|
||||
resolvedDataPolicy = DataPolicy.EMPTY;
|
||||
}
|
||||
else {
|
||||
// Validate that the user-defined Data Policy matches the appropriate Spring GemFire XML namespace
|
||||
// configuration meta-data element for Region (i.e. <gfe:replicated-region .../>)!
|
||||
Assert.isTrue(resolvedDataPolicy.withReplication(), String.format(
|
||||
"Data Policy '%1$s' is not supported in Replicated Regions.", resolvedDataPolicy));
|
||||
}
|
||||
|
||||
// Validate that the data-policy and persistent attributes are compatible when specified!
|
||||
assertDataPolicyAndPersistentAttributesAreCompatible(resolvedDataPolicy);
|
||||
|
||||
regionFactory.setDataPolicy(resolvedDataPolicy);
|
||||
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, DataPolicy dataPolicy) {
|
||||
if (dataPolicy == null) {
|
||||
dataPolicy = (isPersistent() ? DataPolicy.PERSISTENT_REPLICATE : DataPolicy.REPLICATE);
|
||||
}
|
||||
else if (DataPolicy.EMPTY.equals(dataPolicy)) {
|
||||
dataPolicy = DataPolicy.EMPTY;
|
||||
}
|
||||
else {
|
||||
regionFactory.setDataPolicy(isPersistent() ? DataPolicy.PERSISTENT_REPLICATE : DataPolicy.REPLICATE);
|
||||
// Validate that the user-defined Data Policy matches the appropriate Spring GemFire XML namespace
|
||||
// configuration meta-data element for the Region (i.e. <gfe:replicated-region .../>)!
|
||||
Assert.isTrue(dataPolicy.withReplication(), String.format(
|
||||
"Data Policy '%1$s' is not supported in Replicated Regions.", dataPolicy));
|
||||
}
|
||||
|
||||
// Validate that the data-policy and persistent attributes are compatible when both are specified!
|
||||
assertDataPolicyAndPersistentAttributesAreCompatible(dataPolicy);
|
||||
|
||||
regionFactory.setDataPolicy(dataPolicy);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void resolveDataPolicy(RegionFactory<K, V> regionFactory, Boolean persistent, String dataPolicy) {
|
||||
DataPolicy resolvedDataPolicy = null;
|
||||
|
||||
if (dataPolicy != null) {
|
||||
resolvedDataPolicy = new DataPolicyConverter().convert(dataPolicy);
|
||||
Assert.notNull(resolvedDataPolicy, String.format("Data Policy '%1$s' is invalid.", dataPolicy));
|
||||
}
|
||||
|
||||
resolveDataPolicy(regionFactory, persistent, resolvedDataPolicy);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -80,7 +80,7 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
|
||||
ParsingUtils.setPropertyValue(element, builder, "name");
|
||||
ParsingUtils.setPropertyValue(element, builder, "data-policy");
|
||||
ParsingUtils.setPropertyValue(element, builder, "persistent");
|
||||
ParsingUtils.setPropertyValue(element, regionAttributesBuilder, "publisher");
|
||||
ParsingUtils.setPropertyValue(element, builder, "shortcut");
|
||||
|
||||
if (StringUtils.hasText(element.getAttribute("disk-store-ref"))) {
|
||||
ParsingUtils.setPropertyValue(element, builder, "disk-store-ref", "diskStoreName");
|
||||
@@ -147,8 +147,8 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
|
||||
|
||||
private void parseCollectionOfCustomSubElements(Element element, ParserContext parserContext,
|
||||
BeanDefinitionBuilder builder, String className, String subElementName, String propertyName) {
|
||||
List<Element> subElements = DomUtils.getChildElementsByTagName(element,
|
||||
new String[] { subElementName, subElementName + "-ref" });
|
||||
List<Element> subElements = DomUtils.getChildElementsByTagName(element, subElementName,
|
||||
subElementName + "-ref");
|
||||
|
||||
if (!CollectionUtils.isEmpty(subElements)) {
|
||||
ManagedArray array = new ManagedArray(className, subElements.size());
|
||||
@@ -224,4 +224,13 @@ abstract class AbstractRegionParser extends AbstractSingleBeanDefinitionParser {
|
||||
return parentPath;
|
||||
}
|
||||
|
||||
protected void validateDataPolicyShortcutAttributesMutualExclusion(final Element element,
|
||||
final ParserContext parserContext) {
|
||||
if (element.hasAttribute("data-policy") && element.hasAttribute("shortcut")) {
|
||||
parserContext.getReaderContext().error(String.format(
|
||||
"Only one of [data-policy, shortcut] may be specified with element '%1$s'.", element.getTagName()),
|
||||
element);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -49,7 +49,7 @@ class ClientRegionParser extends AbstractRegionParser {
|
||||
protected void doParseRegion(Element element, ParserContext parserContext, BeanDefinitionBuilder builder,
|
||||
boolean subRegion) {
|
||||
|
||||
validateDataPolicyShortcutMutualExclusion(element, parserContext);
|
||||
validateDataPolicyShortcutAttributesMutualExclusion(element, parserContext);
|
||||
|
||||
String resolvedCacheRef = ParsingUtils.resolveCacheReference(element.getAttribute("cache-ref"));
|
||||
|
||||
@@ -114,14 +114,6 @@ class ClientRegionParser extends AbstractRegionParser {
|
||||
}
|
||||
}
|
||||
|
||||
private void validateDataPolicyShortcutMutualExclusion(final Element element, final ParserContext parserContext) {
|
||||
if (element.hasAttribute("data-policy") && element.hasAttribute("shortcut")) {
|
||||
parserContext.getReaderContext().error(String.format(
|
||||
"Only one of [data-policy, shortcut] may be specified with element '%1$s'.", element.getTagName()),
|
||||
element);
|
||||
}
|
||||
}
|
||||
|
||||
private void parseDiskStoreAttribute(final Element element, final BeanDefinitionBuilder builder) {
|
||||
String diskStoreRefAttribute = element.getAttribute("disk-store-ref");
|
||||
|
||||
|
||||
@@ -39,6 +39,8 @@ class LocalRegionParser extends AbstractRegionParser {
|
||||
protected void doParseRegion(Element element, ParserContext parserContext, BeanDefinitionBuilder builder,
|
||||
boolean subRegion) {
|
||||
|
||||
validateDataPolicyShortcutAttributesMutualExclusion(element, parserContext);
|
||||
|
||||
BeanDefinitionBuilder regionAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
RegionAttributesFactoryBean.class);
|
||||
|
||||
|
||||
@@ -303,6 +303,7 @@ abstract class ParsingUtils {
|
||||
|
||||
setPropertyValue(element, regionAttributesBuilder, "cloning-enabled");
|
||||
setPropertyValue(element, regionAttributesBuilder, "concurrency-level");
|
||||
setPropertyValue(element, regionAttributesBuilder, "disk-synchronous");
|
||||
setPropertyValue(element, regionAttributesBuilder, "enable-async-conflation");
|
||||
setPropertyValue(element, regionAttributesBuilder, "enable-subscription-conflation");
|
||||
setPropertyValue(element, regionAttributesBuilder, "ignore-jta", "ignoreJTA");
|
||||
@@ -311,6 +312,7 @@ abstract class ParsingUtils {
|
||||
setPropertyValue(element, regionAttributesBuilder, "key-constraint");
|
||||
setPropertyValue(element, regionAttributesBuilder, "load-factor");
|
||||
setPropertyValue(element, regionAttributesBuilder, "multicast-enabled");
|
||||
setPropertyValue(element, regionAttributesBuilder, "publisher");
|
||||
setPropertyValue(element, regionAttributesBuilder, "value-constraint");
|
||||
|
||||
String indexUpdateType = element.getAttribute("index-update-type");
|
||||
|
||||
@@ -46,10 +46,13 @@ class PartitionedRegionParser extends AbstractRegionParser {
|
||||
return PartitionedRegionFactoryBean.class;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void doParseRegion(Element element, ParserContext parserContext, BeanDefinitionBuilder builder,
|
||||
boolean subRegion) {
|
||||
|
||||
validateDataPolicyShortcutAttributesMutualExclusion(element, parserContext);
|
||||
|
||||
super.doParse(element, builder);
|
||||
|
||||
BeanDefinitionBuilder regionAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
@@ -63,11 +66,11 @@ class PartitionedRegionParser extends AbstractRegionParser {
|
||||
PartitionAttributesFactoryBean.class);
|
||||
|
||||
parseColocatedWith(element, builder, partitionAttributesBuilder, "colocated-with");
|
||||
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "copies","redundantCopies");
|
||||
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "copies", "redundantCopies");
|
||||
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "local-max-memory");
|
||||
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "recovery-delay");
|
||||
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "startup-recovery-delay");
|
||||
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "total-buckets","totalNumBuckets");
|
||||
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "total-buckets", "totalNumBuckets");
|
||||
ParsingUtils.setPropertyValue(element, partitionAttributesBuilder, "total-max-memory");
|
||||
|
||||
Element partitionResolverSubElement = DomUtils.getChildElementByTagName(element, "partition-resolver");
|
||||
|
||||
@@ -40,13 +40,14 @@ class ReplicatedRegionParser extends AbstractRegionParser {
|
||||
protected void doParseRegion(Element element, ParserContext parserContext, BeanDefinitionBuilder builder,
|
||||
boolean subRegion) {
|
||||
|
||||
validateDataPolicyShortcutAttributesMutualExclusion(element, parserContext);
|
||||
|
||||
ParsingUtils.parseScope(element, builder);
|
||||
|
||||
BeanDefinitionBuilder regionAttributesBuilder = BeanDefinitionBuilder.genericBeanDefinition(
|
||||
RegionAttributesFactoryBean.class);
|
||||
|
||||
super.doParseCommonRegionConfiguration(element, parserContext, builder, regionAttributesBuilder,
|
||||
subRegion);
|
||||
super.doParseCommonRegionConfiguration(element, parserContext, builder, regionAttributesBuilder, subRegion);
|
||||
|
||||
builder.addPropertyValue("attributes", regionAttributesBuilder.getBeanDefinition());
|
||||
}
|
||||
|
||||
@@ -129,8 +129,7 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw
|
||||
|
||||
Object instance = instantiator.createInstance(entity, provider);
|
||||
|
||||
final BeanWrapper<PersistentEntity<Object, ?>, Object> wrapper = BeanWrapper
|
||||
.create(instance, conversionService);
|
||||
final BeanWrapper<Object> wrapper = BeanWrapper.create(instance, conversionService);
|
||||
|
||||
entity.doWithProperties(new PropertyHandler<GemfirePersistentProperty>() {
|
||||
@Override
|
||||
@@ -168,7 +167,7 @@ public class MappingPdxSerializer implements PdxSerializer, ApplicationContextAw
|
||||
@Override
|
||||
public boolean toData(Object value, final PdxWriter writer) {
|
||||
GemfirePersistentEntity<?> entity = mappingContext.getPersistentEntity(value.getClass());
|
||||
final BeanWrapper<PersistentEntity<Object, ?>, Object> wrapper = BeanWrapper.create(value, conversionService);
|
||||
final BeanWrapper<Object> wrapper = BeanWrapper.create(value, conversionService);
|
||||
|
||||
entity.doWithProperties(new PropertyHandler<GemfirePersistentProperty>() {
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import com.gemstone.gemfire.cache.client.ClientRegionShortcut;
|
||||
|
||||
/**
|
||||
* The ClientRegionShortcutWrapper enum is a Java enumerated type that wraps GemFire's ClientRegionShortcuts
|
||||
* with Spring Data GemFire ClientRegionShortcutWrapper enumerated values.
|
||||
* <p/>
|
||||
* @author John Blum
|
||||
* @see com.gemstone.gemfire.cache.client.ClientRegionShortcut
|
||||
* @since 1.4.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public enum ClientRegionShortcutWrapper {
|
||||
CACHING_PROXY(ClientRegionShortcut.CACHING_PROXY),
|
||||
CACHING_PROXY_HEAP_LRU(ClientRegionShortcut.CACHING_PROXY_HEAP_LRU),
|
||||
CACHING_PROXY_OVERFLOW(ClientRegionShortcut.CACHING_PROXY_OVERFLOW),
|
||||
LOCAL(ClientRegionShortcut.LOCAL),
|
||||
LOCAL_HEAP_LRU(ClientRegionShortcut.LOCAL_HEAP_LRU),
|
||||
LOCAL_OVERFLOW(ClientRegionShortcut.LOCAL_OVERFLOW),
|
||||
LOCAL_PERSISTENT(ClientRegionShortcut.LOCAL_PERSISTENT),
|
||||
LOCAL_PERSISTENT_OVERFLOW(ClientRegionShortcut.LOCAL_PERSISTENT_OVERFLOW),
|
||||
PROXY(ClientRegionShortcut.PROXY),
|
||||
UNSPECIFIED(null);
|
||||
|
||||
private final ClientRegionShortcut clientRegionShortcut;
|
||||
|
||||
ClientRegionShortcutWrapper(final ClientRegionShortcut clientRegionShortcut) {
|
||||
this.clientRegionShortcut = clientRegionShortcut;
|
||||
}
|
||||
|
||||
public static ClientRegionShortcutWrapper valueOf(final ClientRegionShortcut clientRegionShortcut) {
|
||||
for (ClientRegionShortcutWrapper wrapper : values()) {
|
||||
if (ObjectUtils.nullSafeEquals(wrapper.getClientRegionShortcut(), clientRegionShortcut)) {
|
||||
return wrapper;
|
||||
}
|
||||
}
|
||||
|
||||
return ClientRegionShortcutWrapper.UNSPECIFIED;
|
||||
}
|
||||
|
||||
public ClientRegionShortcut getClientRegionShortcut() {
|
||||
return clientRegionShortcut;
|
||||
}
|
||||
|
||||
public boolean isCaching() {
|
||||
return name().contains("CACHING");
|
||||
}
|
||||
|
||||
public boolean isHeapLru() {
|
||||
return name().contains("HEAP_LRU");
|
||||
}
|
||||
|
||||
public boolean isLocal() {
|
||||
return name().contains("LOCAL");
|
||||
}
|
||||
|
||||
public boolean isOverflow() {
|
||||
return name().contains("OVERFLOW");
|
||||
}
|
||||
|
||||
public boolean isPersistent() {
|
||||
return name().contains("PERSISTENT");
|
||||
}
|
||||
|
||||
public boolean isPersistentOverflow() {
|
||||
return name().contains("PERSISTENT_OVERFLOW");
|
||||
}
|
||||
|
||||
public boolean isProxy() {
|
||||
return name().contains("PROXY");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,115 @@
|
||||
/*
|
||||
* 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.support;
|
||||
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import com.gemstone.gemfire.cache.RegionShortcut;
|
||||
|
||||
/**
|
||||
* The RegionShortcutWrapper enum is a Java enumerated type that wraps GemFire's RegionShortcuts
|
||||
* with Spring Data GemFire RegionShortcutWrapper enumerated values.
|
||||
* <p/>
|
||||
*
|
||||
* @author John Blum
|
||||
* @see com.gemstone.gemfire.cache.RegionShortcut
|
||||
* @since 1.4.0
|
||||
*/
|
||||
@SuppressWarnings("unused")
|
||||
public enum RegionShortcutWrapper {
|
||||
LOCAL(RegionShortcut.LOCAL),
|
||||
LOCAL_HEAP_LRU(RegionShortcut.LOCAL_HEAP_LRU),
|
||||
LOCAL_OVERFLOW(RegionShortcut.LOCAL_OVERFLOW),
|
||||
LOCAL_PERSISTENT(RegionShortcut.LOCAL_PERSISTENT),
|
||||
LOCAL_PERSISTENT_OVERFLOW(RegionShortcut.LOCAL_PERSISTENT_OVERFLOW),
|
||||
PARTITION(RegionShortcut.PARTITION),
|
||||
PARTITION_HEAP_LRU(RegionShortcut.PARTITION_HEAP_LRU),
|
||||
PARTITION_OVERFLOW(RegionShortcut.PARTITION_OVERFLOW),
|
||||
PARTITION_PERSISTENT(RegionShortcut.PARTITION_PERSISTENT),
|
||||
PARTITION_PERSISTENT_OVERFLOW(RegionShortcut.PARTITION_PERSISTENT_OVERFLOW),
|
||||
PARTITION_PROXY(RegionShortcut.PARTITION_PROXY),
|
||||
PARTITION_PROXY_REDUNDANT(RegionShortcut.PARTITION_PROXY_REDUNDANT),
|
||||
PARTITION_REDUNDANT(RegionShortcut.PARTITION_REDUNDANT),
|
||||
PARTITION_REDUNDANT_HEAP_LRU(RegionShortcut.PARTITION_REDUNDANT_HEAP_LRU),
|
||||
PARTITION_REDUNDANT_OVERFLOW(RegionShortcut.PARTITION_REDUNDANT_OVERFLOW),
|
||||
PARTITION_REDUNDANT_PERSISTENT(RegionShortcut.PARTITION_REDUNDANT_PERSISTENT),
|
||||
PARTITION_REDUNDANT_PERSISTENT_OVERFLOW(RegionShortcut.PARTITION_REDUNDANT_PERSISTENT_OVERFLOW),
|
||||
REPLICATE(RegionShortcut.REPLICATE),
|
||||
REPLICATE_HEAP_LRU(RegionShortcut.REPLICATE_HEAP_LRU),
|
||||
REPLICATE_OVERFLOW(RegionShortcut.REPLICATE_OVERFLOW),
|
||||
REPLICATE_PERSISTENT(RegionShortcut.REPLICATE_PERSISTENT),
|
||||
REPLICATE_PERSISTENT_OVERFLOW(RegionShortcut.REPLICATE_PERSISTENT_OVERFLOW),
|
||||
REPLICATE_PROXY(RegionShortcut.REPLICATE_PROXY),
|
||||
UNSPECIFIED(null);
|
||||
|
||||
private final RegionShortcut regionShortcut;
|
||||
|
||||
RegionShortcutWrapper(final RegionShortcut regionShortcut) {
|
||||
this.regionShortcut = regionShortcut;
|
||||
}
|
||||
|
||||
public static RegionShortcutWrapper valueOf(final RegionShortcut regionShortcut) {
|
||||
for (RegionShortcutWrapper wrapper : values()) {
|
||||
if (ObjectUtils.nullSafeEquals(wrapper.getRegionShortcut(), regionShortcut)) {
|
||||
return wrapper;
|
||||
}
|
||||
}
|
||||
|
||||
return RegionShortcutWrapper.UNSPECIFIED;
|
||||
}
|
||||
|
||||
public boolean isHeapLru() {
|
||||
return name().contains("HEAP_LRU");
|
||||
}
|
||||
|
||||
public boolean isLocal() {
|
||||
return name().contains("LOCAL");
|
||||
}
|
||||
|
||||
public boolean isOverflow() {
|
||||
return name().contains("OVERFLOW");
|
||||
}
|
||||
|
||||
public boolean isPartition() {
|
||||
return name().contains("PARTITION");
|
||||
}
|
||||
|
||||
public boolean isPersistent() {
|
||||
return name().contains("PERSISTENT");
|
||||
}
|
||||
|
||||
public boolean isPersistentOverflow() {
|
||||
return (isOverflow() && isPersistent());
|
||||
}
|
||||
|
||||
public boolean isProxy() {
|
||||
return name().contains("PROXY");
|
||||
}
|
||||
|
||||
public boolean isRedundant() {
|
||||
return name().contains("REDUNDANT");
|
||||
}
|
||||
|
||||
public boolean isReplicate() {
|
||||
return name().contains("REPLICATE");
|
||||
}
|
||||
|
||||
public RegionShortcut getRegionShortcut() {
|
||||
return regionShortcut;
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user