+ initial commit
This commit is contained in:
10
.classpath
Normal file
10
.classpath
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/java"/>
|
||||
<classpathentry kind="src" output="target/classes" path="src/main/resources"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/java"/>
|
||||
<classpathentry kind="src" output="target/test-classes" path="src/test/resources"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/J2SE-1.5"/>
|
||||
<classpathentry kind="con" path="org.maven.ide.eclipse.MAVEN2_CLASSPATH_CONTAINER"/>
|
||||
<classpathentry kind="output" path="target/classes"/>
|
||||
</classpath>
|
||||
2
.gitignore
vendored
Normal file
2
.gitignore
vendored
Normal file
@@ -0,0 +1,2 @@
|
||||
target
|
||||
bin
|
||||
29
.project
Normal file
29
.project
Normal file
@@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>spring-gemfire</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.jdt.core.javabuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.maven.ide.eclipse.maven2Builder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.springframework.ide.eclipse.core.springbuilder</name>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.springframework.ide.eclipse.core.springnature</nature>
|
||||
<nature>org.maven.ide.eclipse.maven2Nature</nature>
|
||||
<nature>org.eclipse.jdt.core.javanature</nature>
|
||||
</natures>
|
||||
</projectDescription>
|
||||
13
.settings/org.eclipse.jdt.core.prefs
Normal file
13
.settings/org.eclipse.jdt.core.prefs
Normal file
@@ -0,0 +1,13 @@
|
||||
#Sun Jun 06 11:27:13 EEST 2010
|
||||
eclipse.preferences.version=1
|
||||
org.eclipse.jdt.core.compiler.codegen.inlineJsrBytecode=enabled
|
||||
org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.5
|
||||
org.eclipse.jdt.core.compiler.codegen.unusedLocal=preserve
|
||||
org.eclipse.jdt.core.compiler.compliance=1.5
|
||||
org.eclipse.jdt.core.compiler.debug.lineNumber=generate
|
||||
org.eclipse.jdt.core.compiler.debug.localVariable=generate
|
||||
org.eclipse.jdt.core.compiler.debug.sourceFile=generate
|
||||
org.eclipse.jdt.core.compiler.problem.assertIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.enumIdentifier=error
|
||||
org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning
|
||||
org.eclipse.jdt.core.compiler.source=1.5
|
||||
9
.settings/org.maven.ide.eclipse.prefs
Normal file
9
.settings/org.maven.ide.eclipse.prefs
Normal file
@@ -0,0 +1,9 @@
|
||||
#Fri Jun 04 17:37:03 EEST 2010
|
||||
activeProfiles=
|
||||
eclipse.preferences.version=1
|
||||
fullBuildGoals=process-test-resources
|
||||
includeModules=false
|
||||
resolveWorkspaceProjects=true
|
||||
resourceFilterGoals=process-resources resources\:testResources
|
||||
skipCompilerPlugin=true
|
||||
version=1
|
||||
13
.springBeans
Normal file
13
.springBeans
Normal file
@@ -0,0 +1,13 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beansProjectDescription>
|
||||
<version>1</version>
|
||||
<pluginVersion><![CDATA[2.3.2.201003220227-RELEASE]]></pluginVersion>
|
||||
<configSuffixes>
|
||||
<configSuffix><![CDATA[xml]]></configSuffix>
|
||||
</configSuffixes>
|
||||
<enableImports><![CDATA[false]]></enableImports>
|
||||
<configs>
|
||||
</configs>
|
||||
<configSets>
|
||||
</configSets>
|
||||
</beansProjectDescription>
|
||||
86
pom.xml
Normal file
86
pom.xml
Normal file
@@ -0,0 +1,86 @@
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.springframework.data.gemfire</groupId>
|
||||
<artifactId>spring-gemfire</artifactId>
|
||||
<version>1.0.0.M1-SNAPSHOT</version>
|
||||
<name>Gemfire - Spring Framework Integration</name>
|
||||
|
||||
<properties>
|
||||
<spring.version>3.0.3.RELEASE</spring.version>
|
||||
<junit.version>4.7</junit.version>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>${junit.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-tx</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-webmvc</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.inject</groupId>
|
||||
<artifactId>javax.inject</artifactId>
|
||||
<version>1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.annotation</groupId>
|
||||
<artifactId>jsr250-api</artifactId>
|
||||
<version>1.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${spring.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!--
|
||||
<dependency>
|
||||
<groupId>asm</groupId>
|
||||
<artifactId>asm</artifactId>
|
||||
<version>3.2</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
-->
|
||||
<!-- gemfire dependency -->
|
||||
<dependency>
|
||||
<groupId>gemstone</groupId>
|
||||
<artifactId>gemfire</artifactId>
|
||||
<version>6.0.1</version>
|
||||
<scope>compile</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-compiler-plugin</artifactId>
|
||||
<configuration>
|
||||
<source>1.5</source>
|
||||
<target>1.5</target>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,179 @@
|
||||
/*
|
||||
* Copyright 2010 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 java.util.Properties;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanClassLoaderAware;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.gemstone.gemfire.cache.Cache;
|
||||
import com.gemstone.gemfire.cache.CacheClosedException;
|
||||
import com.gemstone.gemfire.cache.CacheFactory;
|
||||
import com.gemstone.gemfire.distributed.DistributedMember;
|
||||
import com.gemstone.gemfire.distributed.DistributedSystem;
|
||||
|
||||
/**
|
||||
* Factory used for configuring a Gemfire Cache manager. Allows either retrieval of an existing, opened cache
|
||||
* or the creation of a new one.
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanClassLoaderAware, DisposableBean,
|
||||
InitializingBean, FactoryBean<Cache> {
|
||||
|
||||
private static final Log log = LogFactory.getLog(CacheFactoryBean.class);
|
||||
|
||||
private Cache cache;
|
||||
private String name;
|
||||
private Resource cacheXml;
|
||||
private Properties properties;
|
||||
private DistributedSystem system;
|
||||
private ClassLoader beanClassLoader;
|
||||
private GemfireBeanFactoryLocator factoryLocator = new GemfireBeanFactoryLocator();
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
private String beanName;
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
// initialize locator
|
||||
factoryLocator.setBeanFactory(beanFactory);
|
||||
factoryLocator.setBeanName(beanName);
|
||||
factoryLocator.afterPropertiesSet();
|
||||
|
||||
Properties cfgProps = mergeProperties();
|
||||
system = DistributedSystem.connect(cfgProps);
|
||||
|
||||
DistributedMember member = system.getDistributedMember();
|
||||
log.info("Connected to Distributed System ['" + system.getName() + "'=" + member.getId() + "@"
|
||||
+ member.getHost() + "]");
|
||||
|
||||
// use the bean class loader to load Declarable classes
|
||||
Thread th = Thread.currentThread();
|
||||
ClassLoader oldTCCL = th.getContextClassLoader();
|
||||
|
||||
try {
|
||||
th.setContextClassLoader(beanClassLoader);
|
||||
// first look for open caches
|
||||
String msg = null;
|
||||
try {
|
||||
cache = CacheFactory.getInstance(system);
|
||||
msg = "Retrieved existing";
|
||||
} catch (CacheClosedException ex) {
|
||||
// fall back to cache creation
|
||||
cache = CacheFactory.create(system);
|
||||
msg = "Created";
|
||||
}
|
||||
|
||||
log.info(msg + " Gemfire Cache ['" + cache.getName() + "'] v. " + CacheFactory.getVersion());
|
||||
|
||||
// load/init cache.xml
|
||||
if (cacheXml != null) {
|
||||
cache.loadCacheXml(cacheXml.getInputStream());
|
||||
}
|
||||
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("Initialized cache from " + cacheXml);
|
||||
} finally {
|
||||
th.setContextClassLoader(oldTCCL);
|
||||
}
|
||||
}
|
||||
|
||||
private Properties mergeProperties() {
|
||||
Properties cfgProps = new Properties(properties);
|
||||
if (StringUtils.hasText(name)) {
|
||||
cfgProps.setProperty("name", name.trim());
|
||||
}
|
||||
return cfgProps;
|
||||
}
|
||||
|
||||
public void destroy() throws Exception {
|
||||
if (cache != null && !cache.isClosed()) {
|
||||
cache.close();
|
||||
}
|
||||
cache = null;
|
||||
|
||||
if (system != null && system.isConnected()) {
|
||||
system.releaseThreadsSockets();
|
||||
system.disconnect();
|
||||
}
|
||||
system = null;
|
||||
|
||||
factoryLocator.destroy();
|
||||
}
|
||||
|
||||
public Cache getObject() throws Exception {
|
||||
return cache;
|
||||
}
|
||||
|
||||
public Class<? extends Cache> getObjectType() {
|
||||
return (cache != null ? cache.getClass() : Cache.class);
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
public void setBeanClassLoader(ClassLoader classLoader) {
|
||||
this.beanClassLoader = classLoader;
|
||||
}
|
||||
|
||||
public void setBeanName(String name) {
|
||||
this.beanName = name;
|
||||
}
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cache properties.
|
||||
*
|
||||
* @param properties the properties to set
|
||||
*/
|
||||
public void setProperties(Properties properties) {
|
||||
this.properties = properties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the cache.
|
||||
*
|
||||
* @param name the name to set
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cache configuration.
|
||||
*
|
||||
* @param cacheXml the cacheXml to set
|
||||
*/
|
||||
public void setCacheXml(Resource cacheXml) {
|
||||
this.cacheXml = cacheXml;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2010 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 org.springframework.util.Assert;
|
||||
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
|
||||
/**
|
||||
* Client extension for Gemfire regions.
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public class ClientRegionFactoryBean<K, V> extends RegionFactoryBean<K, V> {
|
||||
|
||||
private Interest<K>[] interests;
|
||||
|
||||
@Override
|
||||
protected void postProcess(Region<K, V> region) {
|
||||
Assert.notEmpty(interests);
|
||||
|
||||
for (Interest<K> interest : interests) {
|
||||
if (interest instanceof RegexInterest) {
|
||||
// do the cast since it's safe
|
||||
region.registerInterestRegex((String) interest.getKey(), interest.getPolicy(), interest.isDurable());
|
||||
}
|
||||
else {
|
||||
region.registerInterest(interest.getKey(), interest.getPolicy(), interest.isDurable());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
Region<K, V> region = getObject();
|
||||
// unregister interests
|
||||
try {
|
||||
if (region != null) {
|
||||
for (Interest<K> interest : interests) {
|
||||
if (interest instanceof RegexInterest) {
|
||||
region.unregisterInterestRegex((String) interest.getKey());
|
||||
}
|
||||
else {
|
||||
region.unregisterInterest(interest.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
// should not really happen since interests are validated at start/registration
|
||||
} catch (UnsupportedOperationException ex) {
|
||||
log.warn("Cannot unregister cache interests", ex);
|
||||
}
|
||||
|
||||
super.destroy();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set the interests for this client region. Both key and regex interest are supported.
|
||||
*
|
||||
* @param interests the interests to set
|
||||
*/
|
||||
public void setInterests(Interest<K>[] interests) {
|
||||
this.interests = interests;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the interests
|
||||
*/
|
||||
Interest<K>[] getInterests() {
|
||||
return interests;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* Copyright 2010 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 java.util.Properties;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.access.BeanFactoryReference;
|
||||
|
||||
import com.gemstone.gemfire.cache.CacheCallback;
|
||||
import com.gemstone.gemfire.cache.Declarable;
|
||||
|
||||
/**
|
||||
* Convenience class for Spring-aware GemFire Declarable components.
|
||||
* Provides a reference to the current Spring application context, e.g. for bean lookup or resource loading.
|
||||
*
|
||||
* Note that in most cases, one can just declare the same components as Spring beans, through
|
||||
* {@link RegionFactoryBean} which gives access to the full container capabilities and does not enforce the
|
||||
* {@link Declarable} interface to be implemented.
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public abstract class DeclarableSupport implements CacheCallback, Declarable {
|
||||
|
||||
private String factoryKey = null;
|
||||
private BeanFactoryReference bfReference = null;
|
||||
|
||||
public DeclarableSupport() {
|
||||
}
|
||||
|
||||
/**
|
||||
* This implementation uses this method as a lifecycle hook to initialize
|
||||
* the bean factory locator.
|
||||
*
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @see #setFactoryKey(String)
|
||||
*/
|
||||
public final void init(Properties props) {
|
||||
bfReference = new GemfireBeanFactoryLocator().useBeanFactory(factoryKey);
|
||||
initInstance(props);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialize the current instance based on the given properties.
|
||||
*
|
||||
* @param props
|
||||
*/
|
||||
protected void initInstance(Properties props) {
|
||||
}
|
||||
|
||||
protected BeanFactory getBeanFactory() {
|
||||
return bfReference.getFactory();
|
||||
}
|
||||
|
||||
public void close() {
|
||||
bfReference.release();
|
||||
bfReference = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key under which the enclosing beanFactory can be found.
|
||||
* Needed only if multiple beanFactories are used with GemFire inside
|
||||
* the same class loader / class space.
|
||||
*
|
||||
* @see GemfireBeanFactoryLocator
|
||||
* @param key
|
||||
*/
|
||||
public void setFactoryKey(String key) {
|
||||
this.factoryKey = key;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,158 @@
|
||||
/*
|
||||
* Copyright 2010 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 java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.FatalBeanException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.access.BeanFactoryLocator;
|
||||
import org.springframework.beans.factory.access.BeanFactoryReference;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
/**
|
||||
* {@link BeanFactoryLocator} used for storing Spring application context/bean factory for Gemfire
|
||||
* user components (or {@link com.gemstone.gemfire.cache.Declarable}. As opposed to the "traditional"
|
||||
* {@link org.springframework.beans.factory.access.SingletonBeanFactoryLocator} this implementation does
|
||||
* not require any configuration file; it rather assume declaration inside an application context
|
||||
* (usually through {@link com.gemstone.gemfire.cache.CacheFactory} which it will store under the name
|
||||
* and aliases of the bean (so the same "registry" can be used for storing multiple BeanFactories).
|
||||
* If there is only one BeanFactory registered then a null value can be used with {@link #setBeanName(String)}.
|
||||
*
|
||||
* <p/> In most cases, one does not need to use this class directly as it is used internally
|
||||
* by {@link com.gemstone.gemfire.cache.CacheFactory}.
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public class GemfireBeanFactoryLocator implements BeanFactoryLocator, BeanFactoryAware, BeanNameAware, DisposableBean,
|
||||
InitializingBean {
|
||||
|
||||
private static final Log log = LogFactory.getLog(GemfireBeanFactoryLocator.class);
|
||||
|
||||
// alias/bean name <-> BeanFactory lookup
|
||||
private static final ConcurrentMap<String, BeanFactory> beanFactories = new ConcurrentHashMap<String, BeanFactory>();
|
||||
|
||||
// default factory to return
|
||||
private static volatile boolean canUseDefaultBeanFactory = true;
|
||||
private static volatile BeanFactory defaultFactory = null;
|
||||
|
||||
private static class SimpleBeanFactoryReference implements BeanFactoryReference {
|
||||
|
||||
private BeanFactory bf;
|
||||
|
||||
SimpleBeanFactoryReference(BeanFactory bf) {
|
||||
this.bf = bf;
|
||||
}
|
||||
|
||||
public BeanFactory getFactory() {
|
||||
Assert.notNull(bf, "beanFactory already released or closed");
|
||||
return bf;
|
||||
}
|
||||
|
||||
public void release() throws FatalBeanException {
|
||||
bf = null;
|
||||
}
|
||||
}
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
private String[] names;
|
||||
|
||||
// default factory name
|
||||
private String factoryName = GemfireBeanFactoryLocator.class.getName();
|
||||
|
||||
public void afterPropertiesSet() {
|
||||
// add the factory as default if possible (if it's the only one)
|
||||
synchronized (GemfireBeanFactoryLocator.class) {
|
||||
canUseDefaultBeanFactory = beanFactories.isEmpty();
|
||||
if (canUseDefaultBeanFactory) {
|
||||
if (defaultFactory == null) {
|
||||
defaultFactory = beanFactory;
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("default beanFactoryReference=" + defaultFactory);
|
||||
}
|
||||
else {
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("more then one beanFactory - default not possible to determine");
|
||||
canUseDefaultBeanFactory = false;
|
||||
defaultFactory = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add aliases
|
||||
if (StringUtils.hasText(factoryName)) {
|
||||
String[] aliases = beanFactory.getAliases(factoryName);
|
||||
names = (String[]) ObjectUtils.addObjectToArray(aliases, factoryName);
|
||||
|
||||
for (String name : names) {
|
||||
if (log.isDebugEnabled())
|
||||
log.debug("adding key=" + name + " w/ reference=" + beanFactory);
|
||||
|
||||
if (beanFactories.containsKey(name) || beanFactories.putIfAbsent(name, beanFactory) != null) {
|
||||
throw new IllegalArgumentException("a beanFactoryReference already exists for key " + factoryName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
for (String name : names) {
|
||||
beanFactories.remove(name);
|
||||
}
|
||||
|
||||
if (beanFactory == defaultFactory) {
|
||||
defaultFactory = null;
|
||||
}
|
||||
}
|
||||
|
||||
public BeanFactoryReference useBeanFactory(final String factoryKey) throws BeansException {
|
||||
// see if there is a default FactoryBean
|
||||
BeanFactory factory;
|
||||
|
||||
if (!StringUtils.hasText(factoryKey)) {
|
||||
if (!canUseDefaultBeanFactory)
|
||||
throw new IllegalArgumentException(
|
||||
"a non-null factoryKey needs to be specified as there are more then one factoryKeys available ");
|
||||
factory = defaultFactory;
|
||||
}
|
||||
else {
|
||||
factory = beanFactories.get(factoryKey);
|
||||
if (factory == null)
|
||||
throw new IllegalArgumentException("there is no beanFactory under key " + factoryKey);
|
||||
}
|
||||
|
||||
return new SimpleBeanFactoryReference(factory);
|
||||
}
|
||||
|
||||
public void setBeanName(String name) {
|
||||
factoryName = name;
|
||||
}
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,263 @@
|
||||
/*
|
||||
* Copyright 2010 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 org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.DataAccessResourceFailureException;
|
||||
import org.springframework.dao.DataIntegrityViolationException;
|
||||
import org.springframework.dao.DataRetrievalFailureException;
|
||||
import org.springframework.dao.DuplicateKeyException;
|
||||
import org.springframework.dao.InvalidDataAccessApiUsageException;
|
||||
import org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||
import org.springframework.dao.PermissionDeniedDataAccessException;
|
||||
import org.springframework.dao.PessimisticLockingFailureException;
|
||||
import org.springframework.dao.TypeMismatchDataAccessException;
|
||||
|
||||
import com.gemstone.gemfire.CancelException;
|
||||
import com.gemstone.gemfire.CopyException;
|
||||
import com.gemstone.gemfire.GemFireCacheException;
|
||||
import com.gemstone.gemfire.GemFireCheckedException;
|
||||
import com.gemstone.gemfire.GemFireConfigException;
|
||||
import com.gemstone.gemfire.GemFireException;
|
||||
import com.gemstone.gemfire.GemFireIOException;
|
||||
import com.gemstone.gemfire.IncompatibleSystemException;
|
||||
import com.gemstone.gemfire.InternalGemFireException;
|
||||
import com.gemstone.gemfire.InvalidValueException;
|
||||
import com.gemstone.gemfire.LicenseException;
|
||||
import com.gemstone.gemfire.NoSystemException;
|
||||
import com.gemstone.gemfire.SystemConnectException;
|
||||
import com.gemstone.gemfire.SystemIsRunningException;
|
||||
import com.gemstone.gemfire.UnmodifiableException;
|
||||
import com.gemstone.gemfire.admin.AdminException;
|
||||
import com.gemstone.gemfire.admin.RegionNotFoundException;
|
||||
import com.gemstone.gemfire.admin.RuntimeAdminException;
|
||||
import com.gemstone.gemfire.cache.CacheException;
|
||||
import com.gemstone.gemfire.cache.CacheExistsException;
|
||||
import com.gemstone.gemfire.cache.CacheLoaderException;
|
||||
import com.gemstone.gemfire.cache.CacheRuntimeException;
|
||||
import com.gemstone.gemfire.cache.CacheWriterException;
|
||||
import com.gemstone.gemfire.cache.CacheXmlException;
|
||||
import com.gemstone.gemfire.cache.CommitConflictException;
|
||||
import com.gemstone.gemfire.cache.CommitIncompleteException;
|
||||
import com.gemstone.gemfire.cache.DiskAccessException;
|
||||
import com.gemstone.gemfire.cache.EntryDestroyedException;
|
||||
import com.gemstone.gemfire.cache.EntryExistsException;
|
||||
import com.gemstone.gemfire.cache.EntryNotFoundException;
|
||||
import com.gemstone.gemfire.cache.EntryNotFoundInRegion;
|
||||
import com.gemstone.gemfire.cache.FailedSynchronizationException;
|
||||
import com.gemstone.gemfire.cache.OperationAbortedException;
|
||||
import com.gemstone.gemfire.cache.PartitionedRegionDistributionException;
|
||||
import com.gemstone.gemfire.cache.PartitionedRegionStorageException;
|
||||
import com.gemstone.gemfire.cache.RegionDestroyedException;
|
||||
import com.gemstone.gemfire.cache.RegionExistsException;
|
||||
import com.gemstone.gemfire.cache.ResourceException;
|
||||
import com.gemstone.gemfire.cache.RoleException;
|
||||
import com.gemstone.gemfire.cache.StatisticsDisabledException;
|
||||
import com.gemstone.gemfire.cache.SynchronizationCommitConflictException;
|
||||
import com.gemstone.gemfire.cache.VersionException;
|
||||
import com.gemstone.gemfire.cache.client.ServerConnectivityException;
|
||||
import com.gemstone.gemfire.cache.execute.FunctionException;
|
||||
import com.gemstone.gemfire.cache.query.CqClosedException;
|
||||
import com.gemstone.gemfire.cache.query.IndexMaintenanceException;
|
||||
import com.gemstone.gemfire.cache.query.QueryException;
|
||||
import com.gemstone.gemfire.cache.query.QueryExecutionTimeoutException;
|
||||
import com.gemstone.gemfire.distributed.LeaseExpiredException;
|
||||
import com.gemstone.gemfire.security.GemFireSecurityException;
|
||||
|
||||
/**
|
||||
* Helper class featuring methods for GemFire Cache or Region handling.
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public abstract class GemfireCacheUtils {
|
||||
|
||||
/**
|
||||
* Converts the given (unchecked) Gemfire exception to an appropriate one from the
|
||||
* <code>org.springframework.dao</code> hierarchy.
|
||||
*
|
||||
* @param ex Gemfire unchecked exception
|
||||
* @return new the corresponding DataAccessException instance
|
||||
*/
|
||||
public static DataAccessException convertGemfireAccessException(GemFireException ex) {
|
||||
if (ex instanceof CacheException) {
|
||||
if (ex instanceof CacheExistsException) {
|
||||
return new DataIntegrityViolationException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof CommitConflictException) {
|
||||
return new DataIntegrityViolationException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof CommitIncompleteException) {
|
||||
return new DataIntegrityViolationException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof EntryExistsException) {
|
||||
return new DuplicateKeyException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof EntryNotFoundException) {
|
||||
return new DataRetrievalFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof RegionExistsException) {
|
||||
return new DataIntegrityViolationException(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
if (ex instanceof CacheRuntimeException) {
|
||||
if (ex instanceof CacheXmlException) {
|
||||
return new GemfireSystemException(ex);
|
||||
}
|
||||
if (ex instanceof CancelException) {
|
||||
// all cancellations go wrapped by this exception
|
||||
return new GemfireCancellationException((CancelException) ex);
|
||||
}
|
||||
if (ex instanceof CqClosedException) {
|
||||
return new InvalidDataAccessApiUsageException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof DiskAccessException) {
|
||||
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof EntryDestroyedException) {
|
||||
return new InvalidDataAccessApiUsageException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof FailedSynchronizationException) {
|
||||
return new PessimisticLockingFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof IndexMaintenanceException) {
|
||||
return new GemfireIndexException((IndexMaintenanceException) ex);
|
||||
}
|
||||
if (ex instanceof OperationAbortedException) {
|
||||
// treat user exceptions first
|
||||
if (ex instanceof CacheLoaderException) {
|
||||
return new GemfireSystemException(ex);
|
||||
}
|
||||
if (ex instanceof CacheWriterException) {
|
||||
return new GemfireSystemException(ex);
|
||||
}
|
||||
// the rest are treated as resource failures
|
||||
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof PartitionedRegionDistributionException) {
|
||||
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof PartitionedRegionStorageException) {
|
||||
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof QueryExecutionTimeoutException) {
|
||||
return new GemfireQueryException((QueryExecutionTimeoutException) ex);
|
||||
}
|
||||
if (ex instanceof RegionDestroyedException) {
|
||||
return new InvalidDataAccessResourceUsageException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof RegionNotFoundException) {
|
||||
return new InvalidDataAccessResourceUsageException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof ResourceException) {
|
||||
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof RoleException) {
|
||||
return new GemfireSystemException(ex);
|
||||
}
|
||||
if (ex instanceof StatisticsDisabledException) {
|
||||
return new GemfireSystemException(ex);
|
||||
}
|
||||
if (ex instanceof SynchronizationCommitConflictException) {
|
||||
return new PessimisticLockingFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
if (ex instanceof CopyException) {
|
||||
return new GemfireSystemException(ex);
|
||||
}
|
||||
if (ex instanceof EntryNotFoundInRegion) {
|
||||
return new DataRetrievalFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof FunctionException) {
|
||||
return new InvalidDataAccessApiUsageException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof GemFireCacheException) {
|
||||
return convertGemfireAccessException(((GemFireCacheException) ex).getCacheException());
|
||||
}
|
||||
if (ex instanceof GemFireConfigException) {
|
||||
return new GemfireSystemException(ex);
|
||||
}
|
||||
if (ex instanceof GemFireIOException) {
|
||||
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof GemFireSecurityException) {
|
||||
return new PermissionDeniedDataAccessException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof IncompatibleSystemException) {
|
||||
return new GemfireSystemException(ex);
|
||||
}
|
||||
if (ex instanceof InternalGemFireException) {
|
||||
return new GemfireSystemException(ex);
|
||||
}
|
||||
if (ex instanceof InvalidValueException) {
|
||||
return new TypeMismatchDataAccessException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof LeaseExpiredException) {
|
||||
return new PessimisticLockingFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof LicenseException) {
|
||||
return new GemfireSystemException(ex);
|
||||
}
|
||||
if (ex instanceof NoSystemException) {
|
||||
return new GemfireSystemException(ex);
|
||||
}
|
||||
if (ex instanceof RuntimeAdminException) {
|
||||
return new GemfireSystemException(ex);
|
||||
}
|
||||
if (ex instanceof ServerConnectivityException) {
|
||||
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof SystemConnectException) {
|
||||
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
if (ex instanceof SystemIsRunningException) {
|
||||
return new GemfireSystemException(ex);
|
||||
}
|
||||
if (ex instanceof UnmodifiableException) {
|
||||
return new GemfireSystemException(ex);
|
||||
}
|
||||
// fall back
|
||||
return new GemfireSystemException(ex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the given (checked) Gemfire exception to an appropriate one from the
|
||||
* <code>org.springframework.dao</code> hierarchy.
|
||||
*
|
||||
* @param ex Gemfire unchecked exception
|
||||
* @return new the corresponding DataAccessException instance
|
||||
*/
|
||||
public static DataAccessException convertGemfireAccessException(GemFireCheckedException ex) {
|
||||
// query exceptions
|
||||
if (ex instanceof QueryException) {
|
||||
return new GemfireQueryException((QueryException) ex);
|
||||
}
|
||||
// version exception
|
||||
if (ex instanceof VersionException) {
|
||||
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
// util.version exception (seems quite similar to the exception above)
|
||||
if (ex instanceof com.gemstone.gemfire.cache.util.VersionException) {
|
||||
return new DataAccessResourceFailureException(ex.getMessage(), ex);
|
||||
}
|
||||
// admin exception
|
||||
if (ex instanceof AdminException) {
|
||||
return new GemfireSystemException(ex);
|
||||
}
|
||||
// fall back
|
||||
return new GemfireSystemException(ex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 2010 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 org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||
|
||||
import com.gemstone.gemfire.CancelException;
|
||||
|
||||
/**
|
||||
* GemFire-specific class for exceptions caused by system cancellations.
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public class GemfireCancellationException extends InvalidDataAccessResourceUsageException {
|
||||
|
||||
public GemfireCancellationException(CancelException ex) {
|
||||
super(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 2010 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 org.springframework.dao.DataIntegrityViolationException;
|
||||
|
||||
import com.gemstone.gemfire.cache.query.IndexCreationException;
|
||||
import com.gemstone.gemfire.cache.query.IndexExistsException;
|
||||
import com.gemstone.gemfire.cache.query.IndexMaintenanceException;
|
||||
import com.gemstone.gemfire.cache.query.IndexNameConflictException;
|
||||
|
||||
/**
|
||||
* Gemfire-specific subclass thrown on index creation.
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public class GemfireIndexException extends DataIntegrityViolationException {
|
||||
|
||||
public GemfireIndexException(IndexCreationException ex) {
|
||||
super(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
public GemfireIndexException(IndexExistsException ex) {
|
||||
super(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
public GemfireIndexException(IndexNameConflictException ex) {
|
||||
super(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
public GemfireIndexException(IndexMaintenanceException ex) {
|
||||
super(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 2010 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 org.springframework.dao.InvalidDataAccessResourceUsageException;
|
||||
|
||||
import com.gemstone.gemfire.cache.query.QueryException;
|
||||
import com.gemstone.gemfire.cache.query.QueryExecutionTimeoutException;
|
||||
|
||||
/**
|
||||
* GemFire-specific subclass of {@link InvalidDataAccessResourceUsageException} thrown on invalid
|
||||
* OQL query syntax.
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public class GemfireQueryException extends InvalidDataAccessResourceUsageException {
|
||||
|
||||
public GemfireQueryException(QueryException ex) {
|
||||
super(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
public GemfireQueryException(QueryExecutionTimeoutException ex) {
|
||||
super(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2010 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 org.springframework.dao.UncategorizedDataAccessException;
|
||||
|
||||
import com.gemstone.gemfire.GemFireCheckedException;
|
||||
import com.gemstone.gemfire.GemFireException;
|
||||
|
||||
/**
|
||||
* GemFire-specific subclass of UncategorizedDataAccessException, for GemFire system errors that do not match any concrete <code>org.springframework.dao</code> exceptions.
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public class GemfireSystemException extends UncategorizedDataAccessException {
|
||||
|
||||
public GemfireSystemException(GemFireCheckedException ex) {
|
||||
super(ex.getMessage(), ex);
|
||||
}
|
||||
|
||||
public GemfireSystemException(GemFireException ex) {
|
||||
super(ex.getMessage(), ex);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,257 @@
|
||||
/*
|
||||
* Copyright 2010 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 org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.transaction.CannotCreateTransactionException;
|
||||
import org.springframework.transaction.NoTransactionException;
|
||||
import org.springframework.transaction.PlatformTransactionManager;
|
||||
import org.springframework.transaction.TransactionDefinition;
|
||||
import org.springframework.transaction.TransactionException;
|
||||
import org.springframework.transaction.TransactionSystemException;
|
||||
import org.springframework.transaction.support.AbstractPlatformTransactionManager;
|
||||
import org.springframework.transaction.support.DefaultTransactionStatus;
|
||||
import org.springframework.transaction.support.ResourceTransactionManager;
|
||||
import org.springframework.transaction.support.TransactionSynchronizationManager;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.gemstone.gemfire.cache.Cache;
|
||||
import com.gemstone.gemfire.cache.CacheTransactionManager;
|
||||
import com.gemstone.gemfire.cache.CommitConflictException;
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
|
||||
/**
|
||||
* Local transaction manager for Gemfire Enterprise Fabric (GEF). Provides a {@link PlatformTransactionManager}
|
||||
* implementation for a single Gemfire {@link CacheTransactionManager}.
|
||||
*
|
||||
* Binds one or multiple Gemfire regions for the specified {@link Cache} to the thread, potentially allowing for one
|
||||
* region per cache model.
|
||||
*
|
||||
* <p>
|
||||
* This local strategy is an alternative to executing cache operations within JTA transactions. Its advantage is that
|
||||
* is able to work in any environment, for example a standalone application or a test suite. It is <i>not</i> able to
|
||||
* provide XA transactions, for example to share transactions with data access.
|
||||
*
|
||||
* <p>
|
||||
* To prevent dirty reads, by default, the cache is configured to return copies rather then direct references for
|
||||
* <code>get</code> operations. As a workaround, one could use explicitly deep copy objects before making changes
|
||||
* to them to avoid unnecessary copying on every fetch.
|
||||
*
|
||||
* @see com.gemstone.gemfire.cache.CacheTransactionManager
|
||||
* @see com.gemstone.gemfire.cache.Cache#setCopyOnRead(boolean)
|
||||
* @see com.gemstone.gemfire.cache.Region#get(Object)
|
||||
* @see com.gemstone.gemfire.CopyHelper#copy(Object)
|
||||
* @see #setCopyOnRead(boolean)
|
||||
* @see org.springframework.transaction.support.AbstractPlatformTransactionManager
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
// TODO add lenient behavior if a transaction is already started on the current thread (what should happen then)
|
||||
public class GemfireTransactionManager extends AbstractPlatformTransactionManager implements InitializingBean,
|
||||
ResourceTransactionManager {
|
||||
|
||||
private Cache cache;
|
||||
private boolean copyOnRead = true;
|
||||
|
||||
/**
|
||||
* Creates a new GemfireTransactionManager instance.
|
||||
*/
|
||||
public GemfireTransactionManager() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new GemfireTransactionManager instance.
|
||||
*
|
||||
* @param cache
|
||||
*/
|
||||
public GemfireTransactionManager(Cache cache) {
|
||||
this.cache = cache;
|
||||
afterPropertiesSet();
|
||||
}
|
||||
|
||||
public void afterPropertiesSet() {
|
||||
Assert.notNull(cache, "Cache property is required");
|
||||
cache.setCopyOnRead(copyOnRead);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Object doGetTransaction() throws TransactionException {
|
||||
CacheTransactionObject txObject = new CacheTransactionObject();
|
||||
CacheHolder cacheHolder = (CacheHolder) TransactionSynchronizationManager.getResource(getCache());
|
||||
txObject.setHolder(cacheHolder);
|
||||
return txObject;
|
||||
}
|
||||
|
||||
protected boolean isExistingTransaction(Object transaction) throws TransactionException {
|
||||
CacheTransactionObject txObject = (CacheTransactionObject) transaction;
|
||||
// Consider a pre-bound cache as transaction.
|
||||
return (txObject.getHolder() != null);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doBegin(Object transaction, TransactionDefinition definition) throws TransactionException {
|
||||
CacheTransactionObject txObject = (CacheTransactionObject) transaction;
|
||||
|
||||
Cache cache = null;
|
||||
|
||||
try {
|
||||
cache = getCache();
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("Acquired Cache [" + cache + "] for local Cache transaction");
|
||||
}
|
||||
|
||||
txObject.setHolder(new CacheHolder());
|
||||
cache.getCacheTransactionManager().begin();
|
||||
TransactionSynchronizationManager.bindResource(cache, txObject.getHolder());
|
||||
}
|
||||
|
||||
catch (IllegalStateException ex) {
|
||||
throw new CannotCreateTransactionException(
|
||||
"An ongoing transaction already is already associated with the current thread; are there multiple transaction managers ?",
|
||||
ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doCommit(DefaultTransactionStatus status) throws TransactionException {
|
||||
CacheTransactionObject txObject = (CacheTransactionObject) status.getTransaction();
|
||||
if (status.isDebug()) {
|
||||
logger.debug("Committing Gemfire local transaction on Cache [" + cache + "]");
|
||||
}
|
||||
try {
|
||||
cache.getCacheTransactionManager().commit();
|
||||
} catch (IllegalStateException ex) {
|
||||
throw new NoTransactionException(
|
||||
"No transaction associated with the current thread; are there multiple transaction managers ?", ex);
|
||||
} catch (CommitConflictException ex) {
|
||||
// TODO: can this be replaced with HeuristicCompletionException ?
|
||||
throw new TransactionSystemException("Unexpected failure on commit of Cache local transaction", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doRollback(DefaultTransactionStatus status) throws TransactionException {
|
||||
CacheTransactionObject txObject = (CacheTransactionObject) status.getTransaction();
|
||||
if (status.isDebug()) {
|
||||
logger.debug("Rolling back Cache local transaction for [" + cache + "]");
|
||||
}
|
||||
try {
|
||||
cache.getCacheTransactionManager().rollback();
|
||||
} catch (IllegalStateException ex) {
|
||||
throw new NoTransactionException(
|
||||
"No transaction associated with the current thread; are there multiple transaction managers ?", ex);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doSetRollbackOnly(DefaultTransactionStatus status) {
|
||||
CacheTransactionObject txObject = (CacheTransactionObject) status.getTransaction();
|
||||
if (status.isDebug()) {
|
||||
logger.debug("Setting Gemfire local transaction [" + txObject.getHolder() + "] rollback-only");
|
||||
}
|
||||
txObject.getHolder().setRollbackOnly();
|
||||
}
|
||||
|
||||
protected void doCleanupAfterCompletion(Object transaction) {
|
||||
// Remove the cache holder from the thread.
|
||||
TransactionSynchronizationManager.unbindResource(cache);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final boolean useSavepointForNestedTransaction() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the Cache that this instance manages local transactions for.
|
||||
*
|
||||
* @return Gemfire cache
|
||||
*/
|
||||
public Cache getCache() {
|
||||
return cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Cache that this instance manages local transactions for.
|
||||
*
|
||||
* @param cache Gemfire cache
|
||||
*/
|
||||
public void setCache(Cache cache) {
|
||||
this.cache = cache;
|
||||
}
|
||||
|
||||
public Object getResourceFactory() {
|
||||
return getCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the Gemfire {@link Region} (as an alternative in setting in the cache directly).
|
||||
*
|
||||
* @param region Gemfire region
|
||||
*/
|
||||
public <K, V> void setRegion(Region<K, V> region) {
|
||||
Assert.notNull(region, "non-null arguments are required");
|
||||
this.cache = region.getCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the cache returns direct references or copies of the objects (default) it manages.
|
||||
* While copies imply additional work for every fetch operation, direct references can cause dirty reads
|
||||
* across concurrent threads in the same VM, whether or not transactions are used.
|
||||
* <p/>
|
||||
* One could explicitly deep copy objects before making changes (for example by using {@link com.gemstone.gemfire.CopyHelper#copy(Object)}
|
||||
* in which case this setting can be set to <code>false</code>. However, unless there is a measurable
|
||||
* performance penalty, the recommendation is to keep this setting to <code>true</code>
|
||||
*
|
||||
* @param copyOnRead whether copies (default) rather then direct references will be returned on
|
||||
* fetch operations
|
||||
*/
|
||||
public void setCopyOnRead(boolean copyOnRead) {
|
||||
this.copyOnRead = copyOnRead;
|
||||
}
|
||||
|
||||
/**
|
||||
* GemfireTM local transaction object.
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
private static class CacheTransactionObject {
|
||||
private CacheHolder cacheHolder;
|
||||
|
||||
public CacheHolder getHolder() {
|
||||
return cacheHolder;
|
||||
}
|
||||
|
||||
public void setHolder(CacheHolder cacheHolder) {
|
||||
this.cacheHolder = cacheHolder;
|
||||
}
|
||||
}
|
||||
|
||||
private static class CacheHolder {
|
||||
|
||||
private boolean rollbackOnly = false;
|
||||
|
||||
|
||||
public boolean isRollbackOnly() {
|
||||
return rollbackOnly;
|
||||
}
|
||||
|
||||
public void setRollbackOnly() {
|
||||
rollbackOnly = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
138
src/main/java/org/springframework/data/gemfire/Interest.java
Normal file
138
src/main/java/org/springframework/data/gemfire/Interest.java
Normal file
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright 2010 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 org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.core.Constants;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.gemstone.gemfire.cache.InterestResultPolicy;
|
||||
|
||||
/**
|
||||
* Basic holder class for registering an interest. Useful for configuring Gemfire caches through XML
|
||||
* and or JavaBeans means.
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public class Interest<K> implements InitializingBean {
|
||||
|
||||
private static final Constants constants = new Constants(InterestResultPolicy.class);
|
||||
|
||||
private K key;
|
||||
private InterestResultPolicy policy = InterestResultPolicy.DEFAULT;
|
||||
private boolean durable = false;
|
||||
|
||||
public Interest() {
|
||||
}
|
||||
|
||||
public Interest(K key) {
|
||||
this(key, InterestResultPolicy.DEFAULT, false);
|
||||
}
|
||||
|
||||
public Interest(K key, InterestResultPolicy policy) {
|
||||
this(key, policy, false);
|
||||
}
|
||||
|
||||
public Interest(K key, String policy) {
|
||||
this(key, policy, false);
|
||||
}
|
||||
|
||||
public Interest(K key, String policy, boolean durable) {
|
||||
this.key = key;
|
||||
this.policy = (InterestResultPolicy) constants.asObject(policy);
|
||||
this.durable = durable;
|
||||
afterPropertiesSet();
|
||||
}
|
||||
|
||||
public Interest(K key, InterestResultPolicy policy, boolean durable) {
|
||||
this.key = key;
|
||||
this.policy = policy;
|
||||
this.durable = durable;
|
||||
afterPropertiesSet();
|
||||
}
|
||||
|
||||
|
||||
public void afterPropertiesSet() {
|
||||
Assert.notNull(key, "a non-null key is required");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the key of interest.
|
||||
*
|
||||
* @return the key
|
||||
*/
|
||||
protected K getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the key of interest.
|
||||
*
|
||||
* @param key the key to set
|
||||
*/
|
||||
public void setKey(K key) {
|
||||
this.key = key;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the interest policy.
|
||||
*
|
||||
* @return the policy
|
||||
*/
|
||||
protected InterestResultPolicy getPolicy() {
|
||||
return policy;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the interest policy. The argument is set as an Object
|
||||
* to be able to accept both InterestResultType instances but also
|
||||
* Strings (for XML configurations).
|
||||
*
|
||||
* @param policy the policy to set
|
||||
*/
|
||||
public void setPolicy(Object policy) {
|
||||
if (policy instanceof InterestResultPolicy) {
|
||||
this.policy = (InterestResultPolicy) policy;
|
||||
}
|
||||
else {
|
||||
if (policy instanceof String) {
|
||||
this.policy = (InterestResultPolicy) constants.asObject((String) policy);
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Unknown argument type for property 'policy'" + policy);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the interest durability.
|
||||
*
|
||||
* @return the durable
|
||||
*/
|
||||
protected boolean isDurable() {
|
||||
return durable;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the interest durability.
|
||||
*
|
||||
* @param durable the durable to set
|
||||
*/
|
||||
public void setDurable(boolean durable) {
|
||||
this.durable = durable;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2010 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 org.springframework.util.Assert;
|
||||
|
||||
/**
|
||||
* Cache interest based on regular expression rather then individual key types.
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public class RegexInterest extends Interest<String> {
|
||||
|
||||
@Override
|
||||
public void afterPropertiesSet() {
|
||||
super.afterPropertiesSet();
|
||||
Assert.hasText(getKey(), "A non-empty regex is required");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the regex backing this interest.
|
||||
* Similar to {@link #getKey()}.
|
||||
*
|
||||
* @return interest regex
|
||||
*/
|
||||
//TODO: is this really required
|
||||
public String getRegex() {
|
||||
return getKey();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,214 @@
|
||||
/*
|
||||
* Copyright 2010 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 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.core.io.Resource;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
|
||||
import com.gemstone.gemfire.cache.AttributesFactory;
|
||||
import com.gemstone.gemfire.cache.Cache;
|
||||
import com.gemstone.gemfire.cache.CacheListener;
|
||||
import com.gemstone.gemfire.cache.CacheLoader;
|
||||
import com.gemstone.gemfire.cache.CacheWriter;
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
import com.gemstone.gemfire.cache.RegionAttributes;
|
||||
|
||||
/**
|
||||
* FactoryBean for creating generic Gemfire {@link Region}s.
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public class RegionFactoryBean<K, V> implements DisposableBean, FactoryBean<Region<K, V>>, InitializingBean {
|
||||
|
||||
protected final Log log = LogFactory.getLog(getClass());
|
||||
|
||||
private Cache cache;
|
||||
private String name;
|
||||
private boolean destroy = false;
|
||||
private Resource snapshot;
|
||||
|
||||
private CacheListener<K, V> cacheListeners[];
|
||||
private CacheLoader<K, V> cacheLoader;
|
||||
private CacheWriter<K, V> cacheWriter;
|
||||
|
||||
private RegionAttributes<K, V> attributes;
|
||||
|
||||
private Region<K, V> region;
|
||||
|
||||
public void afterPropertiesSet() throws Exception {
|
||||
Assert.notNull(cache, "Cache property must be set");
|
||||
Assert.hasText(name, "Name property must be set");
|
||||
|
||||
// first get cache
|
||||
region = cache.getRegion(name);
|
||||
if (region != null) {
|
||||
log.info("Retrieved region [" + name + "] from cache");
|
||||
}
|
||||
// fall back to cache creation if one is not found
|
||||
else {
|
||||
if (attributes != null)
|
||||
AttributesFactory.validateAttributes(attributes);
|
||||
|
||||
AttributesFactory<K, V> attrFactory = (attributes != null ? new AttributesFactory<K, V>(attributes)
|
||||
: new AttributesFactory<K, V>());
|
||||
if (!ObjectUtils.isEmpty(cacheListeners)) {
|
||||
for (CacheListener<K, V> listener : cacheListeners) {
|
||||
attrFactory.addCacheListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
if (cacheLoader != null) {
|
||||
attrFactory.setCacheLoader(cacheLoader);
|
||||
}
|
||||
|
||||
if (cacheWriter != null) {
|
||||
attrFactory.setCacheWriter(cacheWriter);
|
||||
}
|
||||
|
||||
region = cache.createRegion(name, attrFactory.create());
|
||||
log.info("Created new cache region [" + name + "]");
|
||||
if (snapshot != null) {
|
||||
region.loadSnapshot(snapshot.getInputStream());
|
||||
}
|
||||
}
|
||||
|
||||
postProcess(region);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
*/
|
||||
protected void postProcess(Region<K, V> region) {
|
||||
// do nothing
|
||||
}
|
||||
|
||||
public void destroy() throws Exception {
|
||||
if (region != null && destroy) {
|
||||
region.destroyRegion();
|
||||
}
|
||||
region = null;
|
||||
}
|
||||
|
||||
public Region<K, V> getObject() throws Exception {
|
||||
return region;
|
||||
}
|
||||
|
||||
public Class<?> getObjectType() {
|
||||
return (region != null ? region.getClass() : Region.class);
|
||||
}
|
||||
|
||||
public boolean isSingleton() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cache used for creating the region.
|
||||
*
|
||||
* @see org.springframework.data.gemfire.CacheFactoryBean
|
||||
* @param cache the cache to set
|
||||
*/
|
||||
public void setCache(Cache cache) {
|
||||
this.cache = cache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the name of the cache region. If no cache is found under
|
||||
* the given name, a new one will be created.
|
||||
*
|
||||
* @see com.gemstone.gemfire.cache.Region#getFullPath()
|
||||
*
|
||||
* @param name the region name
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether the region referred by this factory bean,
|
||||
* will be destroyed on shutdown (default false).
|
||||
*
|
||||
* @param destroy the destroy to set
|
||||
*/
|
||||
public void setDestroy(boolean destroy) {
|
||||
this.destroy = destroy;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 - if the region
|
||||
* already exists, no loading will be performed.
|
||||
*
|
||||
* @see #setName(String)
|
||||
* @param snapshot the snapshot to set
|
||||
*/
|
||||
public void setSnapshot(Resource snapshot) {
|
||||
this.snapshot = snapshot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cache listeners used for the region used by this factory.
|
||||
* Used only when a new region is created.Overrides the settings
|
||||
* specified through {@link #setAttributes(RegionAttributes)}.
|
||||
*
|
||||
* @param cacheListeners the cacheListeners to set on a newly created region
|
||||
*/
|
||||
public void setCacheListeners(CacheListener<K, V>[] cacheListeners) {
|
||||
this.cacheListeners = cacheListeners;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cache loader used for the region used by this factory.
|
||||
* Used only when a new region is created.Overrides the settings
|
||||
* specified through {@link #setAttributes(RegionAttributes)}.
|
||||
*
|
||||
* @param cacheLoader the cacheLoader to set on a newly created region
|
||||
*/
|
||||
public void setCacheLoader(CacheLoader<K, V> cacheLoader) {
|
||||
this.cacheLoader = cacheLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cache loader used for the region used by this factory.
|
||||
* Used only when a new region is created. Overrides the settings
|
||||
* specified through {@link #setAttributes(RegionAttributes)}.
|
||||
*
|
||||
* @param cacheWriter the cacheWriter to set on a newly created region
|
||||
*/
|
||||
public void setCacheWriter(CacheWriter<K, V> cacheWriter) {
|
||||
this.cacheWriter = cacheWriter;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the cache loader used for the region used by this factory.
|
||||
* Used only when a new region is created.
|
||||
*
|
||||
* @param attributes the attributes to set on a newly created region
|
||||
*/
|
||||
public void setAttributes(RegionAttributes<K, V> attributes) {
|
||||
this.attributes = attributes;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2010 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 java.util.Properties;
|
||||
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.wiring.BeanConfigurerSupport;
|
||||
import org.springframework.beans.factory.wiring.BeanWiringInfo;
|
||||
import org.springframework.beans.factory.wiring.BeanWiringInfoResolver;
|
||||
|
||||
import com.gemstone.gemfire.cache.Declarable;
|
||||
|
||||
/**
|
||||
* Dedicated {@link Declarable} support class for wiring the declaring instance through
|
||||
* the Spring container.
|
||||
* This implementation will first look for a 'bean-name' property which will be used to
|
||||
* locate a 'template' bean definition. In case the property is not given, a bean named
|
||||
* after the class will be searched and if none is found, autowiring will be performed,
|
||||
* based on the settings defined in the Spring container.
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public class WiringDeclarableSupport extends DeclarableSupport {
|
||||
|
||||
private final String BEAN_NAME_PROP = "bean-name";
|
||||
|
||||
@Override
|
||||
protected void initInstance(Properties props) {
|
||||
BeanFactory bf = getBeanFactory();
|
||||
BeanConfigurerSupport configurer = new BeanConfigurerSupport();
|
||||
configurer.setBeanFactory(bf);
|
||||
|
||||
final String beanName = props.getProperty(BEAN_NAME_PROP);
|
||||
// key specified, search for a bean
|
||||
if (beanName != null) {
|
||||
if (!bf.containsBean(beanName)) {
|
||||
throw new IllegalArgumentException("Cannot find bean named '" + beanName + "'");
|
||||
}
|
||||
configurer.setBeanWiringInfoResolver(new BeanWiringInfoResolver() {
|
||||
|
||||
public BeanWiringInfo resolveWiringInfo(Object beanInstance) {
|
||||
return new BeanWiringInfo(beanName);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
configurer.afterPropertiesSet();
|
||||
configurer.configureBean(this);
|
||||
configurer.destroy();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,247 @@
|
||||
/*
|
||||
* Copyright 2010 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.serialization;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.springframework.asm.ClassWriter;
|
||||
import org.springframework.asm.FieldVisitor;
|
||||
import org.springframework.asm.MethodVisitor;
|
||||
import org.springframework.asm.Opcodes;
|
||||
import org.springframework.asm.Type;
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.util.Assert;
|
||||
|
||||
import com.gemstone.gemfire.DataSerializable;
|
||||
import com.gemstone.gemfire.Instantiator;
|
||||
|
||||
/**
|
||||
* ASM based {@link InstantiatorFactory} implementation. This class relies on ASM 2.x package
|
||||
* repacked by Spring framework to minimize the number of dependencies and avoid any versioning
|
||||
* confusion.
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public class AsmInstantiatorGenerator implements InstantiatorGenerator, Opcodes {
|
||||
|
||||
private static final String PKG = "org/springextensions/gef/serialization";
|
||||
private static final String CLASS_LABEL = "Instantiator$Synthetic";
|
||||
private static final String INSTANTIATOR_NAME = Type.getInternalName(Instantiator.class);
|
||||
private static final String SERIALIZABLE_NAME = Type.getInternalName(Serializable.class);
|
||||
private static final String CLASS_DESCRIPTOR = Type.getDescriptor(Class.class);
|
||||
private static final String CLASS_FIELD_NAME = "clazz";
|
||||
private static final String ID_FIELD_NAME = "classId";
|
||||
|
||||
private static final String INIT = "<init>";
|
||||
private static final String CINIT = "<clinit>";
|
||||
private static final String NEW_INSTANCE = "newInstance";
|
||||
private static final String NEW_INSTANCE_DESC = Type.getMethodDescriptor(Type.getType(DataSerializable.class),
|
||||
new Type[] {});
|
||||
|
||||
// generated class counter
|
||||
private static final AtomicLong counter = new AtomicLong(1);
|
||||
|
||||
// class cache
|
||||
private final ConcurrentMap<Class<? extends DataSerializable>, Instantiator> cache = new ConcurrentHashMap<Class<? extends DataSerializable>, Instantiator>();
|
||||
|
||||
|
||||
private static final class BytecodeClassLoader extends ClassLoader {
|
||||
|
||||
public BytecodeClassLoader(ClassLoader loader) {
|
||||
super(loader);
|
||||
}
|
||||
|
||||
public Class<?> loadClass(String name, byte[] bytecode) {
|
||||
return defineClass(name, bytecode, 0, bytecode.length);
|
||||
}
|
||||
}
|
||||
|
||||
private final BytecodeClassLoader classLoader;
|
||||
|
||||
public AsmInstantiatorGenerator() {
|
||||
this(AsmInstantiatorGenerator.class.getClassLoader());
|
||||
}
|
||||
|
||||
public AsmInstantiatorGenerator(ClassLoader classLoader) {
|
||||
Assert.notNull(classLoader);
|
||||
this.classLoader = new BytecodeClassLoader(classLoader);
|
||||
}
|
||||
|
||||
public Instantiator getInstantiator(Class<? extends DataSerializable> clazz, int classId) {
|
||||
Instantiator instantiator = cache.get(clazz);
|
||||
if (instantiator == null) {
|
||||
synchronized (cache) {
|
||||
instantiator = cache.get(clazz);
|
||||
if (instantiator == null) {
|
||||
// create Instantiator
|
||||
instantiator = createInstantiator(clazz, classId);
|
||||
cache.putIfAbsent(clazz, instantiator);
|
||||
}
|
||||
}
|
||||
}
|
||||
return instantiator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an instance of the custom instantiator created for the given class.
|
||||
*
|
||||
* @param clazz
|
||||
* @param classId
|
||||
* @return
|
||||
*/
|
||||
private Instantiator createInstantiator(Class<? extends DataSerializable> clazz, int classId) {
|
||||
validateClass(clazz);
|
||||
Class<?> clz = createCustomInstantiatorClass(clazz, classId);
|
||||
return (Instantiator) BeanUtils.instantiate(clz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Does basic sanity checks to make sure the constructor can be properly invoked by our generated
|
||||
* class.
|
||||
*
|
||||
* @param clazz
|
||||
*/
|
||||
private void validateClass(Class<? extends DataSerializable> clazz) {
|
||||
Assert.isTrue(!Modifier.isAbstract(clazz.getModifiers()), "Cannot instantiate abstract classes");
|
||||
Assert.isTrue(Modifier.isPublic(clazz.getModifiers()), "Only public classes are supported");
|
||||
try {
|
||||
Constructor<? extends DataSerializable> ctor = clazz.getConstructor();
|
||||
Assert.isTrue(Modifier.isPublic(ctor.getModifiers()), "Default constructor is not public");
|
||||
|
||||
} catch (Exception ex) {
|
||||
throw new IllegalArgumentException("Class " + clazz + " unsuitable for instantiation", ex);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Generates a new Instantiator class for the given custom class.
|
||||
*
|
||||
* The generated class has the following definition:
|
||||
*
|
||||
* <pre>
|
||||
* package org.springframework.data.gemfire.serialization;
|
||||
*
|
||||
* public class <<i>T</i>>Instantiator$Synthetic<i>Counter</i> extends Instantiator implements Serializable {
|
||||
*
|
||||
* private static final Class<<i>T</i>> clazz = T.class;
|
||||
* private static final int classId = <i>value</i>;
|
||||
*
|
||||
* public DateInstantiator() {
|
||||
* this(clazz, classId);
|
||||
* }
|
||||
*
|
||||
* public DateInstantiator(Class<? extends DataSerializable> c, int classId) {
|
||||
* super(c, classId);
|
||||
* }
|
||||
*
|
||||
* public <i>T</i> newInstance() {
|
||||
* return new <i>T</i>();
|
||||
* }
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* @param clazz
|
||||
* @return
|
||||
*/
|
||||
Class<?> createCustomInstantiatorClass(Class<? extends DataSerializable> clazz, int classId) {
|
||||
String classInternalName = PKG + clazz.getSimpleName() + CLASS_LABEL + counter.getAndIncrement();
|
||||
byte[] bytecode = generateClassBytecode(classInternalName, clazz, classId);
|
||||
// translate internal name to binary form
|
||||
return classLoader.loadClass(classInternalName.replace('/', '.'), bytecode);
|
||||
}
|
||||
|
||||
byte[] generateClassBytecode(String className, Class<? extends DataSerializable> clazz, int classId) {
|
||||
ClassWriter cw = new ClassWriter(false);
|
||||
|
||||
cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, className, null, INSTANTIATOR_NAME, new String[] { SERIALIZABLE_NAME });
|
||||
FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL + ACC_STATIC, CLASS_FIELD_NAME, CLASS_DESCRIPTOR, null,
|
||||
null);
|
||||
fv.visitEnd();
|
||||
fv = cw.visitField(ACC_PRIVATE + ACC_FINAL + ACC_STATIC, ID_FIELD_NAME, Type.INT_TYPE.getDescriptor(), null,
|
||||
Integer.valueOf(classId));
|
||||
fv.visitEnd();
|
||||
|
||||
String voidNoArgMethodDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {});
|
||||
|
||||
// field class loading
|
||||
MethodVisitor mv = cw.visitMethod(ACC_STATIC, CINIT, voidNoArgMethodDescriptor, null, null);
|
||||
mv.visitCode();
|
||||
mv.visitLdcInsn(Type.getType(clazz));
|
||||
mv.visitFieldInsn(PUTSTATIC, className, CLASS_FIELD_NAME, CLASS_DESCRIPTOR);
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(1, 0);
|
||||
mv.visitEnd();
|
||||
|
||||
String voidArgClassAndIntDescriptor = Type.getMethodDescriptor(Type.VOID_TYPE, new Type[] {
|
||||
Type.getType(Class.class), Type.INT_TYPE });
|
||||
|
||||
// default constructor
|
||||
mv = cw.visitMethod(ACC_PUBLIC, INIT, voidNoArgMethodDescriptor, null, null);
|
||||
mv.visitCode();
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitFieldInsn(GETSTATIC, className, CLASS_FIELD_NAME, CLASS_DESCRIPTOR);
|
||||
mv.visitFieldInsn(GETSTATIC, className, ID_FIELD_NAME, Type.INT_TYPE.getDescriptor());
|
||||
mv.visitMethodInsn(INVOKESPECIAL, className, INIT, voidArgClassAndIntDescriptor);
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(3, 1);
|
||||
mv.visitEnd();
|
||||
|
||||
// two-arg constructor
|
||||
mv = cw.visitMethod(ACC_PUBLIC, INIT, voidArgClassAndIntDescriptor, null, null);
|
||||
mv.visitCode();
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitVarInsn(ALOAD, 1);
|
||||
mv.visitVarInsn(ILOAD, 2);
|
||||
mv.visitMethodInsn(INVOKESPECIAL, INSTANTIATOR_NAME, INIT, voidArgClassAndIntDescriptor);
|
||||
mv.visitInsn(RETURN);
|
||||
mv.visitMaxs(3, 3);
|
||||
mv.visitEnd();
|
||||
|
||||
Type customClassType = Type.getType(clazz);
|
||||
String customTypeNoArgDesc = Type.getMethodDescriptor(customClassType, new Type[] {});
|
||||
|
||||
// newInstance overloaded method
|
||||
mv = cw.visitMethod(ACC_PUBLIC, NEW_INSTANCE, customTypeNoArgDesc, null, null);
|
||||
|
||||
mv.visitCode();
|
||||
mv.visitTypeInsn(NEW, customClassType.getInternalName());
|
||||
mv.visitInsn(DUP);
|
||||
mv.visitMethodInsn(INVOKESPECIAL, customClassType.getInternalName(), INIT, voidNoArgMethodDescriptor);
|
||||
mv.visitInsn(ARETURN);
|
||||
mv.visitMaxs(2, 1);
|
||||
mv.visitEnd();
|
||||
|
||||
// plus original method signature
|
||||
mv = cw.visitMethod(ACC_PUBLIC + ACC_BRIDGE + ACC_SYNTHETIC, NEW_INSTANCE, NEW_INSTANCE_DESC, null, null);
|
||||
mv.visitCode();
|
||||
mv.visitVarInsn(ALOAD, 0);
|
||||
mv.visitMethodInsn(INVOKEVIRTUAL, className, NEW_INSTANCE, customTypeNoArgDesc);
|
||||
mv.visitInsn(ARETURN);
|
||||
mv.visitMaxs(1, 1);
|
||||
mv.visitEnd();
|
||||
|
||||
// end class generation
|
||||
cw.visitEnd();
|
||||
|
||||
return cw.toByteArray();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,101 @@
|
||||
/*
|
||||
* Copyright 2010 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.serialization;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import com.gemstone.gemfire.DataSerializer;
|
||||
import com.gemstone.gemfire.internal.InternalDataSerializer;
|
||||
|
||||
/**
|
||||
* Generic Serializer for JDK Enums. The class needs to be registered only once - custom enums
|
||||
* will be then understood by the converter by calling {@link #addEnum(Class)}.
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public class EnumSerializer extends DataSerializer implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = -7069461993489626976L;
|
||||
|
||||
private static final ConcurrentMap<Class<?>, Enum[]> supportedClasses = new ConcurrentHashMap<Class<?>, Enum[]>();
|
||||
|
||||
private int id = 1024;
|
||||
|
||||
@Override
|
||||
public boolean toData(Object o, DataOutput out) throws IOException {
|
||||
if (o instanceof Enum<?>) {
|
||||
// add enum to the set
|
||||
Enum<?> enm = (Enum<?>) o;
|
||||
Class<?> cls = enm.getDeclaringClass();
|
||||
addEnum(cls);
|
||||
DataSerializer.writeClass(cls, out);
|
||||
out.writeInt(enm.ordinal());
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public Object fromData(DataInput in) throws IOException, ClassNotFoundException {
|
||||
Class cls = DataSerializer.readClass(in);
|
||||
if (cls.isEnum()) {
|
||||
addEnum(cls);
|
||||
int ordinal = in.readInt();
|
||||
return supportedClasses.get(cls)[ordinal];
|
||||
}
|
||||
throw new IOException("Non-enum class read from the stream -" + cls);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public void addEnum(Class enumClass) {
|
||||
if (!supportedClasses.containsKey(enumClass)) {
|
||||
supportedClasses.put(enumClass, (Enum[]) enumClass.getEnumConstants());
|
||||
}
|
||||
|
||||
// if registered, re-register the serializer to propagate the changes
|
||||
if (InternalDataSerializer.getSerializer(getId()) != null) {
|
||||
if (InternalDataSerializer.getSerializer(enumClass) == null) {
|
||||
InternalDataSerializer.unregister(getId());
|
||||
InternalDataSerializer.register(getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?>[] getSupportedClasses() {
|
||||
return supportedClasses.keySet().toArray(new Class<?>[supportedClasses.size()]);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the id for this serializer. Default is 1024;
|
||||
*
|
||||
* @param id the id to set
|
||||
*/
|
||||
public void setId(int id) {
|
||||
this.id = id;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2010 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.serialization;
|
||||
|
||||
import com.gemstone.gemfire.DataSerializable;
|
||||
import com.gemstone.gemfire.Instantiator;
|
||||
|
||||
/**
|
||||
* Factory that generates {@link Instantiator} classes to improve instantiation of
|
||||
* custom types.
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public interface InstantiatorGenerator {
|
||||
|
||||
/**
|
||||
* Returns a (potentially new) Instantiator that optimizes the instantiation of the given types.
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Instantiator getInstantiator(Class<? extends DataSerializable> clazz, int classId);
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 2010 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.serialization;
|
||||
|
||||
import org.springframework.beans.BeanUtils;
|
||||
import org.springframework.beans.BeansException;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.BeanFactoryAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.wiring.BeanConfigurerSupport;
|
||||
|
||||
import com.gemstone.gemfire.DataSerializable;
|
||||
import com.gemstone.gemfire.Instantiator;
|
||||
|
||||
/**
|
||||
* Instantiator that performs instance wiring using the Spring IoC container, allowing common properties
|
||||
* to be injected before the object is hydrated/deserialized. The newly created instances can be configured
|
||||
* either by relying on an existing bean definition (which acts as a template) or by providing an embedded
|
||||
* configuration through annotations.
|
||||
*
|
||||
* <p/>
|
||||
* Can reuse existing instantiators to optimize instance creation. If one is not provided, it will fallback
|
||||
* to reflection invocation.
|
||||
*
|
||||
* @see org.springframework.beans.factory.wiring.BeanConfigurerSupport
|
||||
* @see org.springframework.beans.factory.wiring.BeanWiringInfoResolver
|
||||
* @see org.springframework.beans.factory.annotation.Autowired
|
||||
* @see javax.annotation.Resource
|
||||
* @see javax.inject.Inject
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public class WiringInstantiator extends Instantiator implements BeanFactoryAware, InitializingBean,
|
||||
DisposableBean {
|
||||
|
||||
private final Instantiator instantiator;
|
||||
private final Class<? extends DataSerializable> clazz;
|
||||
private BeanConfigurerSupport configurer;
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
public WiringInstantiator(Instantiator instantiator) {
|
||||
super(instantiator.getInstantiatedClass(), instantiator.getId());
|
||||
this.instantiator = instantiator;
|
||||
this.clazz = null;
|
||||
}
|
||||
|
||||
public WiringInstantiator(Class<? extends DataSerializable> c, int classId) {
|
||||
super(c, classId);
|
||||
instantiator = null;
|
||||
clazz = c;
|
||||
}
|
||||
|
||||
|
||||
public void afterPropertiesSet() {
|
||||
if (configurer == null) {
|
||||
configurer = new BeanConfigurerSupport();
|
||||
configurer.setBeanFactory(beanFactory);
|
||||
configurer.afterPropertiesSet();
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() throws Exception {
|
||||
configurer.destroy();
|
||||
}
|
||||
|
||||
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
|
||||
this.beanFactory = beanFactory;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public DataSerializable newInstance() {
|
||||
DataSerializable instance = createInstance();
|
||||
configurer.configureBean(instance);
|
||||
return instance;
|
||||
}
|
||||
|
||||
private DataSerializable createInstance() {
|
||||
if (instantiator != null) {
|
||||
return instantiator.newInstance();
|
||||
}
|
||||
|
||||
return BeanUtils.instantiate(clazz);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the manager responsible for configuring the newly created instances.
|
||||
* The given configurer needs to be configured and initialized before-hand.
|
||||
*
|
||||
* @param configurer the configurer to set
|
||||
*/
|
||||
public void setConfigurer(BeanConfigurerSupport configurer) {
|
||||
this.configurer = configurer;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,66 @@
|
||||
/*
|
||||
* Copyright 2010 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 org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.annotation.DirtiesContext.ClassMode;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import com.gemstone.gemfire.cache.Cache;
|
||||
|
||||
/**
|
||||
* Integration test trying various basic configurations of Gemfire through Spring.
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = { "basic-cache.xml" })
|
||||
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
|
||||
public class CacheIntegrationTest {
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext ctx;
|
||||
|
||||
@Test
|
||||
public void testBasicCache() throws Exception {
|
||||
ctx.getBean("default-cache");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCacheWithProps() throws Exception {
|
||||
Cache cache = ctx.getBean("cache-with-props", Cache.class);
|
||||
// the name property seems to be ignored
|
||||
// Assert.assertEquals("cache-with-props", cache.getDistributedSystem().getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNamedCache() throws Exception {
|
||||
ctx.getBean("named-cache");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCacheWithXml() throws Exception {
|
||||
Cache cache = ctx.getBean("cache-with-xml", Cache.class);
|
||||
//Assert.assertEquals("cache-with-props", cache.getDistributedSystem().getName());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* Copyright 2010 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.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.annotation.DirtiesContext.ClassMode;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
|
||||
/**
|
||||
* Integration test for declarable support (and GEF bean factory locator).
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = { "cache-with-declarable-ctx.xml" })
|
||||
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
|
||||
public class DeclarableSupportTest {
|
||||
|
||||
@Autowired
|
||||
private BeanFactory ctx;
|
||||
|
||||
@Test
|
||||
public void testUserObject() throws Exception {
|
||||
assertNotNull(UserObject.THIS);
|
||||
UserObject obj = UserObject.THIS;
|
||||
assertSame(ctx, obj.getBeanFactory());
|
||||
assertSame(ctx.getBean("bean"), obj.getProp2());
|
||||
assertEquals("Enescu", obj.getProp1());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Copyright 2010 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.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.fail;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.access.BeanFactoryReference;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.data.gemfire.GemfireBeanFactoryLocator;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
/**
|
||||
* @author Costin Leau
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = { "locatorContext.xml" })
|
||||
public class GemfireBeanFactoryLocatorTest {
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext applicationContext;
|
||||
|
||||
private GemfireBeanFactoryLocator locator1, locator2;
|
||||
private String INSTANCE_1 = "instance1";
|
||||
private String INSTANCE_2 = "instance2";
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
locator1 = new GemfireBeanFactoryLocator();
|
||||
locator1.setBeanName(INSTANCE_1);
|
||||
locator1.setBeanFactory(applicationContext);
|
||||
locator1.afterPropertiesSet();
|
||||
|
||||
locator2 = new GemfireBeanFactoryLocator();
|
||||
locator2.setBeanName(INSTANCE_2);
|
||||
locator2.setBeanFactory(applicationContext);
|
||||
locator2.afterPropertiesSet();
|
||||
}
|
||||
|
||||
@After
|
||||
public void destroy() {
|
||||
BeanFactoryReference ref1;
|
||||
try {
|
||||
ref1 = locator1.useBeanFactory(INSTANCE_1);
|
||||
ref1.release();
|
||||
BeanFactoryReference ref2 = locator2.useBeanFactory(INSTANCE_2);
|
||||
ref2.release();
|
||||
|
||||
} catch (IllegalArgumentException e) {
|
||||
// it's okay
|
||||
}
|
||||
locator1.destroy();
|
||||
locator2.destroy();
|
||||
locator1 = null;
|
||||
locator2 = null;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testBeanFactoryRelease() throws Exception {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFactoryLocator() throws Exception {
|
||||
BeanFactoryReference reference1 = locator1.useBeanFactory(INSTANCE_1);
|
||||
BeanFactoryReference reference2 = locator2.useBeanFactory(INSTANCE_2);
|
||||
BeanFactoryReference aliasRef1 = locator1.useBeanFactory("alias1");
|
||||
BeanFactoryReference aliasRef2 = locator1.useBeanFactory("alias2");
|
||||
|
||||
// verify the static map
|
||||
BeanFactory factory1 = reference1.getFactory();
|
||||
BeanFactory factory2 = reference2.getFactory();
|
||||
BeanFactory factory3 = reference2.getFactory();
|
||||
// get the alias from different factories
|
||||
BeanFactory alias1 = aliasRef1.getFactory();
|
||||
BeanFactory alias2 = aliasRef2.getFactory();
|
||||
|
||||
assertSame(factory1, factory2);
|
||||
assertSame(factory1, factory3);
|
||||
// verify it's the same bean factory as the application context
|
||||
assertSame(factory1, applicationContext);
|
||||
|
||||
// verify aliases
|
||||
assertSame(alias1, alias2);
|
||||
assertSame(factory1, alias1);
|
||||
|
||||
aliasRef1.release();
|
||||
aliasRef2.release();
|
||||
reference1.release();
|
||||
reference2.release();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testDefaultFactoryLocator() throws Exception {
|
||||
try {
|
||||
locator1.useBeanFactory(null);
|
||||
fail("there are more then one bean factories registered - should have thrown exception");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// it's okay
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testFactoryLocatorContract() throws Exception {
|
||||
BeanFactoryReference factory1 = locator1.useBeanFactory(INSTANCE_1);
|
||||
assertNotNull(factory1.getFactory());
|
||||
|
||||
factory1.release();
|
||||
try {
|
||||
factory1.getFactory();
|
||||
fail("should have received exception");
|
||||
} catch (IllegalArgumentException e) {
|
||||
// it's okay
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 2010 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.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertSame;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.data.gemfire.ClientRegionFactoryBean;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.annotation.DirtiesContext.ClassMode;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import com.gemstone.gemfire.cache.CacheListener;
|
||||
import com.gemstone.gemfire.cache.CacheLoader;
|
||||
import com.gemstone.gemfire.cache.CacheLoaderException;
|
||||
import com.gemstone.gemfire.cache.LoaderHelper;
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
import com.gemstone.gemfire.cache.util.CacheListenerAdapter;
|
||||
import com.gemstone.gemfire.cache.util.CacheWriterAdapter;
|
||||
|
||||
|
||||
/**
|
||||
* @author Costin Leau
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = { "basic-region.xml" })
|
||||
@DirtiesContext(classMode = ClassMode.AFTER_EACH_TEST_METHOD)
|
||||
public class RegionIntegrationTest {
|
||||
|
||||
private static class CacheList<K, V> extends CacheListenerAdapter<K, V> {
|
||||
}
|
||||
|
||||
private static class CacheLoad<K, V> implements CacheLoader<K, V> {
|
||||
|
||||
public V load(LoaderHelper<K, V> arg0) throws CacheLoaderException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void close() {
|
||||
}
|
||||
}
|
||||
|
||||
private static class CacheWrite<K, V> extends CacheWriterAdapter<K, V> {
|
||||
}
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext ctx;
|
||||
|
||||
@Test
|
||||
public void testBasicRegion() throws Exception {
|
||||
Region region = ctx.getBean("basic", Region.class);
|
||||
assertEquals("basic", region.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExistingRegion() throws Exception {
|
||||
Region region = ctx.getBean("root", Region.class);
|
||||
// the name property seems to be ignored
|
||||
assertEquals("root", region.getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRegionWithListeners() throws Exception {
|
||||
Region region = ctx.getBean("listeners", Region.class);
|
||||
assertEquals("listeners", region.getName());
|
||||
CacheListener[] listeners = region.getAttributes().getCacheListeners();
|
||||
assertEquals(2, listeners.length);
|
||||
assertSame(CacheList.class, listeners[0].getClass());
|
||||
assertSame(CacheLoad.class, region.getAttributes().getCacheLoader().getClass());
|
||||
assertSame(CacheWrite.class, region.getAttributes().getCacheWriter().getClass());
|
||||
}
|
||||
|
||||
//@Test
|
||||
//TODO: Disabled since for some reason in Spring, I get the bean rather then the client
|
||||
public void testRegionInterest() throws Exception {
|
||||
ClientRegionFactoryBean regionFB = (ClientRegionFactoryBean) ctx.getBean("&basic-client");
|
||||
System.out.println("**** interests are " + Arrays.toString(regionFB.getInterests()));
|
||||
//BeanDefinition bd = ((BeanDefinitionRegistry) ctx.getAutowireCapableBeanFactory()).getBeanDefinition("basic-client");
|
||||
// System.out.println(bd.getPropertyValues().getPropertyValue("interests").getValue());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Copyright 2010 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.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.test.annotation.Rollback;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.test.context.transaction.AfterTransaction;
|
||||
import org.springframework.test.context.transaction.BeforeTransaction;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
/**
|
||||
* Simple TX integration test.
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration(locations = { "basic-tx-config.xml" })
|
||||
@Transactional
|
||||
public class TxIntegrationTest {
|
||||
|
||||
@Resource(name = "rollback-region")
|
||||
private Map<String, String> rollbackRegion;
|
||||
@Resource(name = "commit-region")
|
||||
private Map<String, String> commitRegion;
|
||||
|
||||
private boolean txCommit = false;
|
||||
|
||||
@BeforeTransaction
|
||||
public void addItemsToTheCache() {
|
||||
rollbackRegion.put("Vlaicu", "Aurel");
|
||||
rollbackRegion.put("Coanda", "Henri");
|
||||
commitRegion.put("Coanda", "Henri");
|
||||
commitRegion.put("Vlaicu", "Aurel");
|
||||
txCommit = false;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTransactionRollback() throws Exception {
|
||||
rollbackRegion.remove("Coanda");
|
||||
rollbackRegion.put("Ciurcu", "Alexandru");
|
||||
}
|
||||
|
||||
@Test
|
||||
@Rollback(value = false)
|
||||
public void testTransactionCommit() throws Exception {
|
||||
commitRegion.put("Poenaru", "Petrache");
|
||||
commitRegion.remove("Coanda");
|
||||
commitRegion.put("Vlaicu", "A");
|
||||
|
||||
txCommit = true;
|
||||
}
|
||||
|
||||
@AfterTransaction
|
||||
public void testTxOutcome() {
|
||||
if (txCommit) {
|
||||
assertFalse(commitRegion.containsKey("Coanda"));
|
||||
assertTrue(commitRegion.containsKey("Poenaru"));
|
||||
assertTrue(commitRegion.containsValue("A"));
|
||||
}
|
||||
assertTrue(rollbackRegion.containsKey("Coanda"));
|
||||
assertTrue(rollbackRegion.containsKey("Vlaicu"));
|
||||
assertFalse(rollbackRegion.containsKey("Ciurcu"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* Copyright 2010 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 org.springframework.data.gemfire.WiringDeclarableSupport;
|
||||
|
||||
import com.gemstone.gemfire.cache.CacheLoader;
|
||||
import com.gemstone.gemfire.cache.CacheLoaderException;
|
||||
import com.gemstone.gemfire.cache.LoaderHelper;
|
||||
|
||||
/**
|
||||
* User object used for testing Spring wiring.
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public class UserObject extends WiringDeclarableSupport implements CacheLoader {
|
||||
|
||||
public static UserObject THIS;
|
||||
|
||||
private String prop1;
|
||||
private Object prop2;
|
||||
|
||||
public UserObject() {
|
||||
System.out.println("Initialized");
|
||||
THIS = this;
|
||||
}
|
||||
|
||||
public Object load(LoaderHelper helper) throws CacheLoaderException {
|
||||
return new Object();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the prop1
|
||||
*/
|
||||
public String getProp1() {
|
||||
return prop1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param prop1 the prop1 to set
|
||||
*/
|
||||
public void setProp1(String prop1) {
|
||||
this.prop1 = prop1;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the prop2
|
||||
*/
|
||||
public Object getProp2() {
|
||||
return prop2;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param prop2 the prop2 to set
|
||||
*/
|
||||
public void setProp2(Object prop2) {
|
||||
this.prop2 = prop2;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Copyright 2010 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.serialization;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.data.gemfire.serialization.AsmInstantiatorGenerator;
|
||||
|
||||
import com.gemstone.gemfire.DataSerializable;
|
||||
import com.gemstone.gemfire.Instantiator;
|
||||
|
||||
/**
|
||||
* @author Costin Leau
|
||||
*/
|
||||
public class AsmInstantiatorFactoryTest {
|
||||
|
||||
public static class SomeClass implements DataSerializable {
|
||||
public static boolean instantiated = false;
|
||||
|
||||
public SomeClass() {
|
||||
instantiated = true;
|
||||
}
|
||||
|
||||
public void fromData(DataInput in) throws IOException, ClassNotFoundException {
|
||||
}
|
||||
|
||||
public void toData(DataOutput out) throws IOException {
|
||||
}
|
||||
}
|
||||
|
||||
private AsmInstantiatorGenerator asmFactory = null;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
SomeClass.instantiated = false;
|
||||
asmFactory = new AsmInstantiatorGenerator();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClassGeneration() throws Exception {
|
||||
Instantiator instantiator = asmFactory.getInstantiator(SomeClass.class, 100);
|
||||
assertEquals(100, instantiator.getId());
|
||||
assertEquals(SomeClass.class, instantiator.getInstantiatedClass());
|
||||
Object instance = instantiator.newInstance();
|
||||
assertEquals(SomeClass.class, instance.getClass());
|
||||
assertTrue(SomeClass.instantiated);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGeneratedClassName() throws Exception {
|
||||
Instantiator instantiator = asmFactory.getInstantiator(SomeClass.class, 100);
|
||||
assertTrue(instantiator.getClass().getName().contains("$"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInterfaces() throws Exception {
|
||||
Instantiator instantiator = asmFactory.getInstantiator(SomeClass.class, 100);
|
||||
assertTrue(instantiator instanceof Serializable);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCacheInPlace() throws Exception {
|
||||
Instantiator instance1 = asmFactory.getInstantiator(SomeClass.class, 120);
|
||||
Instantiator instance2 = asmFactory.getInstantiator(SomeClass.class, 125);
|
||||
assertSame(instance1, instance2);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/*
|
||||
* Copyright 2010 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.serialization;
|
||||
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.awt.Point;
|
||||
import java.awt.Shape;
|
||||
import java.beans.Beans;
|
||||
import java.io.DataInput;
|
||||
import java.io.DataOutput;
|
||||
import java.io.IOException;
|
||||
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ApplicationContext;
|
||||
import org.springframework.data.gemfire.serialization.AsmInstantiatorGenerator;
|
||||
import org.springframework.data.gemfire.serialization.WiringInstantiator;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
|
||||
import com.gemstone.gemfire.DataSerializable;
|
||||
|
||||
/**
|
||||
* @author Costin Leau
|
||||
*/
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@ContextConfiguration("simple-config.xml")
|
||||
public class WiringInstantiatorTest {
|
||||
|
||||
@Autowired
|
||||
private ApplicationContext ctx;
|
||||
@Autowired
|
||||
private WiringInstantiator instantiator;
|
||||
|
||||
|
||||
public static class AnnotatedBean implements DataSerializable {
|
||||
@Autowired
|
||||
Point point;
|
||||
Shape shape;
|
||||
|
||||
@Autowired
|
||||
void initShape(Shape shape) {
|
||||
this.shape = shape;
|
||||
}
|
||||
|
||||
public void fromData(DataInput in) throws IOException, ClassNotFoundException {
|
||||
}
|
||||
|
||||
public void toData(DataOutput out) throws IOException {
|
||||
}
|
||||
}
|
||||
|
||||
public static class TemplateWiringBean implements DataSerializable {
|
||||
Point point;
|
||||
Beans beans;
|
||||
|
||||
public void setBeans(Beans bs) {
|
||||
this.beans = bs;
|
||||
}
|
||||
|
||||
public void fromData(DataInput in) throws IOException, ClassNotFoundException {
|
||||
}
|
||||
|
||||
public void toData(DataOutput out) throws IOException {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testAutowiredBean() throws Exception {
|
||||
Object instance = instantiator.newInstance();
|
||||
assertNotNull(instance);
|
||||
assertTrue(instance instanceof AnnotatedBean);
|
||||
AnnotatedBean bean = (AnnotatedBean) instance;
|
||||
|
||||
assertNotNull(bean.point);
|
||||
assertNotNull(bean.shape);
|
||||
|
||||
assertSame(bean.point, ctx.getBean("point"));
|
||||
assertSame(bean.shape, ctx.getBean("area"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTemplateBean() throws Exception {
|
||||
WiringInstantiator instantiator2 = new WiringInstantiator(
|
||||
new AsmInstantiatorGenerator().getInstantiator(
|
||||
TemplateWiringBean.class, 99));
|
||||
instantiator2.setBeanFactory(ctx.getAutowireCapableBeanFactory());
|
||||
instantiator2.afterPropertiesSet();
|
||||
|
||||
Object instance = instantiator2.newInstance();
|
||||
|
||||
assertTrue(instance instanceof TemplateWiringBean);
|
||||
TemplateWiringBean bean = (TemplateWiringBean) instance;
|
||||
|
||||
assertTrue(bean.point == null);
|
||||
assertNotNull(bean.beans);
|
||||
|
||||
assertSame(bean.beans, ctx.getBean("beans"));
|
||||
}
|
||||
}
|
||||
32
src/test/resources/cache-with-declarable.xml
Normal file
32
src/test/resources/cache-with-declarable.xml
Normal file
@@ -0,0 +1,32 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE cache PUBLIC "-//GemStone Systems, Inc.//GemFire Declarative Caching 5.7//EN" "http://www.gemstone.com/dtd/cache5_7.dtd">
|
||||
<cache lock-lease="120" lock-timeout="60" search-timeout="300">
|
||||
<region-attributes id="attTemplate" scope="local" data-policy="normal" initial-capacity="16" load-factor="0.75" concurrency-level="16" statistics-enabled="true">
|
||||
<key-constraint>java.lang.String</key-constraint>
|
||||
<cache-loader>
|
||||
<class-name>org.springframework.data.gemfire.UserObject</class-name>
|
||||
</cache-loader>
|
||||
|
||||
</region-attributes>
|
||||
<region name="root">
|
||||
<region-attributes refid="attTemplate" scope="distributed-no-ack">
|
||||
<region-time-to-live>
|
||||
<expiration-attributes timeout="0" action="invalidate"/>
|
||||
</region-time-to-live>
|
||||
<region-idle-time>
|
||||
<expiration-attributes timeout="0" action="invalidate"/>
|
||||
</region-idle-time>
|
||||
<entry-time-to-live>
|
||||
<expiration-attributes timeout="0" action="invalidate"/>
|
||||
</entry-time-to-live>
|
||||
<entry-idle-time>
|
||||
<expiration-attributes timeout="0" action="invalidate"/>
|
||||
</entry-idle-time>
|
||||
</region-attributes>
|
||||
<entry>
|
||||
<key><string>Application Version</string></key>
|
||||
<value><string>1.0</string></value>
|
||||
</entry>
|
||||
</region>
|
||||
|
||||
</cache>
|
||||
39
src/test/resources/cache.xml
Normal file
39
src/test/resources/cache.xml
Normal file
@@ -0,0 +1,39 @@
|
||||
<?xml version="1.0"?>
|
||||
<!DOCTYPE cache PUBLIC "-//GemStone Systems, Inc.//GemFire Declarative Caching 5.7//EN" "http://www.gemstone.com/dtd/cache5_7.dtd">
|
||||
<cache lock-lease="120" lock-timeout="60" search-timeout="300">
|
||||
<region-attributes id="attTemplate" scope="local" data-policy="normal" initial-capacity="16" load-factor="0.75" concurrency-level="16" statistics-enabled="true">
|
||||
<key-constraint>java.lang.String</key-constraint>
|
||||
</region-attributes>
|
||||
<region name="root">
|
||||
<region-attributes refid="attTemplate" scope="distributed-no-ack">
|
||||
<region-time-to-live>
|
||||
<expiration-attributes timeout="0" action="invalidate"/>
|
||||
</region-time-to-live>
|
||||
<region-idle-time>
|
||||
<expiration-attributes timeout="0" action="invalidate"/>
|
||||
</region-idle-time>
|
||||
<entry-time-to-live>
|
||||
<expiration-attributes timeout="0" action="invalidate"/>
|
||||
</entry-time-to-live>
|
||||
<entry-idle-time>
|
||||
<expiration-attributes timeout="0" action="invalidate"/>
|
||||
</entry-idle-time>
|
||||
</region-attributes>
|
||||
<entry>
|
||||
<key><string>Application Version</string></key>
|
||||
<value><string>1.0</string></value>
|
||||
</entry>
|
||||
<region name="rlocal">
|
||||
<region-attributes refid="attTemplate">
|
||||
</region-attributes>
|
||||
</region>
|
||||
<region name="rdistnoack">
|
||||
<region-attributes refid="attTemplate" scope="distributed-no-ack">
|
||||
</region-attributes>
|
||||
</region>
|
||||
<region name="rglobalreplication">
|
||||
<region-attributes refid="attTemplate" scope="global" data-policy="replicate">
|
||||
</region-attributes>
|
||||
</region>
|
||||
</region>
|
||||
</cache>
|
||||
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-lazy-init="true">
|
||||
|
||||
<!-- all beans are lazy to allow the same config to be used between multiple tests -->
|
||||
<!-- as there can be only one cache per VM -->
|
||||
<bean id="default-cache" class="org.springframework.data.gemfire.CacheFactoryBean"/>
|
||||
|
||||
<bean id="cache-with-props" class="org.springframework.data.gemfire.CacheFactoryBean">
|
||||
<property name="properties">
|
||||
<props>
|
||||
<prop key="name">cache-with-props</prop>
|
||||
</props>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="named-cache" class="org.springframework.data.gemfire.CacheFactoryBean" p:name="named-cache">
|
||||
<property name="properties">
|
||||
<props>
|
||||
<prop key="name">cache-with-props</prop>
|
||||
</props>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
<bean id="cache-with-xml" class="org.springframework.data.gemfire.CacheFactoryBean">
|
||||
<property name="cacheXml" value="classpath:cache.xml"/>
|
||||
</bean>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,38 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-lazy-init="true">
|
||||
|
||||
<!-- all beans are lazy to allow the same config to be used between multiple tests -->
|
||||
<!-- as there can be only one cache per VM -->
|
||||
<bean id="cache" class="org.springframework.data.gemfire.CacheFactoryBean"/>
|
||||
|
||||
<bean id="basic" class="org.springframework.data.gemfire.RegionFactoryBean" p:cache-ref="cache" p:name="basic"/>
|
||||
|
||||
<!-- find existing region -->
|
||||
<bean id="root" class="org.springframework.data.gemfire.RegionFactoryBean" p:cache-ref="cache" p:name="root"/>
|
||||
|
||||
<bean id="listeners" class="org.springframework.data.gemfire.RegionFactoryBean" p:cache-ref="cache" p:name="listeners">
|
||||
<property name="cacheListeners">
|
||||
<array>
|
||||
<bean class="org.springframework.data.gemfire.RegionIntegrationTest$CacheList"/>
|
||||
<bean class="org.springframework.data.gemfire.RegionIntegrationTest$CacheList"/>
|
||||
</array>
|
||||
</property>
|
||||
<property name="cacheLoader"><bean class="org.springframework.data.gemfire.RegionIntegrationTest$CacheLoad"/></property>
|
||||
<property name="cacheWriter"><bean class="org.springframework.data.gemfire.RegionIntegrationTest$CacheWrite"/></property>
|
||||
</bean>
|
||||
|
||||
<!-- client configurations -->
|
||||
<bean id="basic-client" class="org.springframework.data.gemfire.ClientRegionFactoryBean" p:cache-ref="cache" p:name="client-region" lazy-init="true">
|
||||
<property name="interests">
|
||||
<array>
|
||||
<bean class="org.springframework.data.gemfire.Interest" p:key="Vlaicu" p:policy="NONE"/>
|
||||
<bean class="org.springframework.data.gemfire.RegexInterest" p:key=".*" p:policy="KEYS" p:durable="true"/>
|
||||
</array>
|
||||
</property>
|
||||
</bean>
|
||||
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd" default-lazy-init="true">
|
||||
|
||||
<bean id="cache" class="org.springframework.data.gemfire.CacheFactoryBean"/>
|
||||
|
||||
<bean id="transactionManager" class="org.springframework.data.gemfire.GemfireTransactionManager" p:cache-ref="cache"/>
|
||||
|
||||
<bean id="rollback-region" class="org.springframework.data.gemfire.RegionFactoryBean" p:name="r-region" p:cache-ref="cache"/>
|
||||
<bean id="commit-region" class="org.springframework.data.gemfire.RegionFactoryBean" p:name="c-region" p:cache-ref="cache"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
|
||||
|
||||
<bean id="cache-with-declarable" class="org.springframework.data.gemfire.CacheFactoryBean">
|
||||
<property name="cacheXml" value="classpath:cache-with-declarable.xml"/>
|
||||
</bean>
|
||||
|
||||
<bean id="bean" class="java.lang.Object"/>
|
||||
|
||||
<bean abstract="true" class="org.springframework.data.gemfire.UserObject" p:prop1="Enescu" p:prop2-ref="bean"/>
|
||||
|
||||
</beans>
|
||||
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
|
||||
|
||||
<!--
|
||||
Context used for testing GemfireBFLocator - usually, one doesn't have to declare the them inside
|
||||
the context. see the javadocs for more details.
|
||||
-->
|
||||
<beans>
|
||||
<bean id="instance1" name="alias1, alias2" class="java.lang.Object"/>
|
||||
<bean id="instance2" class="java.lang.Object"/>
|
||||
</beans>
|
||||
@@ -0,0 +1,28 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xmlns:context="http://www.springframework.org/schema/context"
|
||||
xmlns:p="http://www.springframework.org/schema/p"
|
||||
xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||
http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd">
|
||||
|
||||
<context:annotation-config/>
|
||||
|
||||
<bean id="point" class="java.awt.Point"/>
|
||||
|
||||
<bean id="area" class="java.awt.geom.Area"/>
|
||||
<bean id="beans" class="java.beans.Beans"/>
|
||||
|
||||
<bean id="generator" class="org.springframework.data.gemfire.serialization.AsmInstantiatorGenerator"/>
|
||||
|
||||
<bean id="instantiator" class="org.springframework.data.gemfire.serialization.WiringInstantiator">
|
||||
<constructor-arg>
|
||||
<bean factory-bean="generator" factory-method="getInstantiator">
|
||||
<constructor-arg value="org.springframework.data.gemfire.serialization.WiringInstantiatorTest$AnnotatedBean"/>
|
||||
<constructor-arg value="95"/>
|
||||
</bean>
|
||||
</constructor-arg>
|
||||
</bean>
|
||||
|
||||
<bean class="org.springframework.data.gemfire.serialization.WiringInstantiatorTest$TemplateWiringBean" abstract="true" p:beans-ref="beans"/>
|
||||
</beans>
|
||||
Reference in New Issue
Block a user