+ 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