SGF-67 - In progress

This commit is contained in:
David Turanski
2012-11-26 08:44:46 -05:00
parent f71120138b
commit efdc27666e
127 changed files with 5208 additions and 1583 deletions

View File

@@ -5,7 +5,7 @@ log4jVersion = 1.2.16
slf4jVersion = 1.6.4 slf4jVersion = 1.6.4
# Common libraries # Common libraries
springVersion = 3.1.2.RELEASE springVersion = 3.2.0.RC1
springDataCommonsVersion = 1.4.0.RELEASE springDataCommonsVersion = 1.4.0.RELEASE
gemfireVersion = 7.0 gemfireVersion = 7.0

View File

@@ -31,6 +31,7 @@ import org.springframework.beans.factory.BeanNameAware;
import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.FactoryBean; import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean; import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.dao.DataAccessException; import org.springframework.dao.DataAccessException;
import org.springframework.dao.support.PersistenceExceptionTranslator; import org.springframework.dao.support.PersistenceExceptionTranslator;
@@ -75,12 +76,14 @@ import com.gemstone.gemfire.pdx.PdxSerializer;
* @author David Turanski * @author David Turanski
*/ */
public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanClassLoaderAware, DisposableBean, public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanClassLoaderAware, DisposableBean,
InitializingBean, FactoryBean<GemFireCache>, PersistenceExceptionTranslator { InitializingBean, FactoryBean<GemFireCache>, PersistenceExceptionTranslator {
/** /**
* Inner class to avoid a hard dependency on the GemFire 6.6 API. * Inner class to avoid a hard dependency on the GemFire 6.6 API.
* *
* @author Costin Leau * @author Costin Leau
*/ */
private class PdxOptions implements Runnable { private class PdxOptions implements Runnable {
private final CacheFactory factory; private final CacheFactory factory;
@@ -277,10 +280,11 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
factoryLocator.afterPropertiesSet(); factoryLocator.afterPropertiesSet();
} }
Properties cfgProps = mergeProperties(); Properties cfgProps = mergeProperties();
// use the bean class loader to load Declarable classes // use the bean class loader to load Declarable classes
Thread th = Thread.currentThread(); Thread th = Thread.currentThread();
ClassLoader oldTCCL = th.getContextClassLoader(); ClassLoader oldTCCL = th.getContextClassLoader();
try { try {
th.setContextClassLoader(beanClassLoader); th.setContextClassLoader(beanClassLoader);
@@ -329,6 +333,7 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
log.debug("Initialized cache from " + cacheXml); log.debug("Initialized cache from " + cacheXml);
} }
} }
setHeapPercentages(); setHeapPercentages();
registerTransactionListeners(); registerTransactionListeners();
registerTransactionWriter(); registerTransactionWriter();
@@ -680,4 +685,7 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
public void setJndiDataSources(List<JndiDataSource> jndiDataSources) { public void setJndiDataSources(List<JndiDataSource> jndiDataSources) {
this.jndiDataSources = jndiDataSources; this.jndiDataSources = jndiDataSources;
} }
} }

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2002-2012 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.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
/**
*
* Work around to ensure dependent disk stores are created before gateway senders
*
* @author David Turanski
*
*/
public class GemfireBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
private DefaultListableBeanFactory beanFactory;
/* (non-Javadoc)
* @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String)
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String)
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org.springframework.beans.factory.BeanFactory)
*/
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = (DefaultListableBeanFactory)beanFactory;
}
}

View File

@@ -40,6 +40,5 @@ public interface GemfireCallback<T> {
* @param region GemFire Region * @param region GemFire Region
* @return a result object, or <tt>null</tt> if none * @return a result object, or <tt>null</tt> if none
*/ */
@SuppressWarnings("unchecked") T doInGemfire(Region<?,?> region) throws GemFireCheckedException, GemFireException;
T doInGemfire(Region region) throws GemFireCheckedException, GemFireException;
} }

View File

@@ -25,6 +25,7 @@ import com.gemstone.gemfire.CancelException;
* *
* @author Costin Leau * @author Costin Leau
*/ */
@SuppressWarnings("serial")
public class GemfireCancellationException extends InvalidDataAccessResourceUsageException { public class GemfireCancellationException extends InvalidDataAccessResourceUsageException {
public GemfireCancellationException(CancelException ex) { public GemfireCancellationException(CancelException ex) {

View File

@@ -29,6 +29,7 @@ import com.gemstone.gemfire.cache.query.IndexNameConflictException;
* *
* @author Costin Leau * @author Costin Leau
*/ */
@SuppressWarnings("serial")
public class GemfireIndexException extends DataIntegrityViolationException { public class GemfireIndexException extends DataIntegrityViolationException {
public GemfireIndexException(IndexCreationException ex) { public GemfireIndexException(IndexCreationException ex) {

View File

@@ -28,6 +28,7 @@ import com.gemstone.gemfire.cache.query.QueryInvalidException;
* *
* @author Costin Leau * @author Costin Leau
*/ */
@SuppressWarnings("serial")
public class GemfireQueryException extends InvalidDataAccessResourceUsageException { public class GemfireQueryException extends InvalidDataAccessResourceUsageException {
public GemfireQueryException(String message, QueryException ex) { public GemfireQueryException(String message, QueryException ex) {

View File

@@ -26,6 +26,7 @@ import com.gemstone.gemfire.GemFireException;
* *
* @author Costin Leau * @author Costin Leau
*/ */
@SuppressWarnings("serial")
public class GemfireSystemException extends UncategorizedDataAccessException { public class GemfireSystemException extends UncategorizedDataAccessException {
public GemfireSystemException(GemFireCheckedException ex) { public GemfireSystemException(GemFireCheckedException ex) {

View File

@@ -98,8 +98,7 @@ public class GemfireTemplate extends GemfireAccessor {
public boolean containsKey(final Object key) { public boolean containsKey(final Object key) {
return execute(new GemfireCallback<Boolean>() { return execute(new GemfireCallback<Boolean>() {
@SuppressWarnings("unchecked") public Boolean doInGemfire(Region<?,?> region) throws GemFireCheckedException, GemFireException {
public Boolean doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
return region.containsKey(key); return region.containsKey(key);
} }
}); });
@@ -107,8 +106,7 @@ public class GemfireTemplate extends GemfireAccessor {
public boolean containsKeyOnServer(final Object key) { public boolean containsKeyOnServer(final Object key) {
return execute(new GemfireCallback<Boolean>() { return execute(new GemfireCallback<Boolean>() {
@SuppressWarnings("unchecked") public Boolean doInGemfire(Region<?,?> region) throws GemFireCheckedException, GemFireException {
public Boolean doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
return region.containsKeyOnServer(key); return region.containsKeyOnServer(key);
} }
}); });
@@ -116,8 +114,7 @@ public class GemfireTemplate extends GemfireAccessor {
public boolean containsValue(final Object value) { public boolean containsValue(final Object value) {
return execute(new GemfireCallback<Boolean>() { return execute(new GemfireCallback<Boolean>() {
@SuppressWarnings("unchecked") public Boolean doInGemfire(Region<?,?> region) throws GemFireCheckedException, GemFireException {
public Boolean doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
return region.containsValue(value); return region.containsValue(value);
} }
}); });
@@ -125,8 +122,7 @@ public class GemfireTemplate extends GemfireAccessor {
public boolean containsValueForKey(final Object key) { public boolean containsValueForKey(final Object key) {
return execute(new GemfireCallback<Boolean>() { return execute(new GemfireCallback<Boolean>() {
@SuppressWarnings("unchecked") public Boolean doInGemfire(Region<?,?> region) throws GemFireCheckedException, GemFireException {
public Boolean doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
return region.containsValueForKey(key); return region.containsValueForKey(key);
} }
}); });
@@ -134,7 +130,7 @@ public class GemfireTemplate extends GemfireAccessor {
public <K, V> void create(final K key, final V value) { public <K, V> void create(final K key, final V value) {
execute(new GemfireCallback<Object>() { execute(new GemfireCallback<Object>() {
@SuppressWarnings("unchecked") @SuppressWarnings({ "unchecked", "rawtypes" })
public Object doInGemfire(Region region) throws GemFireCheckedException, GemFireException { public Object doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
region.create(key, value); region.create(key, value);
return null; return null;
@@ -144,7 +140,7 @@ public class GemfireTemplate extends GemfireAccessor {
public <K, V> V get(final K key) { public <K, V> V get(final K key) {
return execute(new GemfireCallback<V>() { return execute(new GemfireCallback<V>() {
@SuppressWarnings("unchecked") @SuppressWarnings({ "unchecked", "rawtypes" })
public V doInGemfire(Region region) throws GemFireCheckedException, GemFireException { public V doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
return (V) region.get(key); return (V) region.get(key);
} }
@@ -153,7 +149,7 @@ public class GemfireTemplate extends GemfireAccessor {
public <K, V> V put(final K key, final V value) { public <K, V> V put(final K key, final V value) {
return execute(new GemfireCallback<V>() { return execute(new GemfireCallback<V>() {
@SuppressWarnings("unchecked") @SuppressWarnings({ "unchecked", "rawtypes" })
public V doInGemfire(Region region) throws GemFireCheckedException, GemFireException { public V doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
return (V) region.put(key, value); return (V) region.put(key, value);
} }
@@ -162,7 +158,7 @@ public class GemfireTemplate extends GemfireAccessor {
public <K, V> V putIfAbsent(final K key, final V value) { public <K, V> V putIfAbsent(final K key, final V value) {
return execute(new GemfireCallback<V>() { return execute(new GemfireCallback<V>() {
@SuppressWarnings("unchecked") @SuppressWarnings({ "unchecked", "rawtypes" })
public V doInGemfire(Region region) throws GemFireCheckedException, GemFireException { public V doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
return (V) region.putIfAbsent(key, value); return (V) region.putIfAbsent(key, value);
} }
@@ -171,7 +167,7 @@ public class GemfireTemplate extends GemfireAccessor {
public <K, V> V remove(final K key) { public <K, V> V remove(final K key) {
return execute(new GemfireCallback<V>() { return execute(new GemfireCallback<V>() {
@SuppressWarnings("unchecked") @SuppressWarnings({ "unchecked", "rawtypes" })
public V doInGemfire(Region region) throws GemFireCheckedException, GemFireException { public V doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
return (V) region.remove(key); return (V) region.remove(key);
} }
@@ -180,7 +176,7 @@ public class GemfireTemplate extends GemfireAccessor {
public <K, V> V replace(final K key, final V value) { public <K, V> V replace(final K key, final V value) {
return execute(new GemfireCallback<V>() { return execute(new GemfireCallback<V>() {
@SuppressWarnings("unchecked") @SuppressWarnings({ "unchecked", "rawtypes" })
public V doInGemfire(Region region) throws GemFireCheckedException, GemFireException { public V doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
return (V) region.replace(key, value); return (V) region.replace(key, value);
} }
@@ -189,7 +185,7 @@ public class GemfireTemplate extends GemfireAccessor {
public <K, V> boolean replace(final K key, final V oldValue, final V newValue) { public <K, V> boolean replace(final K key, final V oldValue, final V newValue) {
return execute(new GemfireCallback<Boolean>() { return execute(new GemfireCallback<Boolean>() {
@SuppressWarnings("unchecked") @SuppressWarnings({ "unchecked", "rawtypes" })
public Boolean doInGemfire(Region region) throws GemFireCheckedException, GemFireException { public Boolean doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
return region.replace(key, oldValue, newValue); return region.replace(key, oldValue, newValue);
} }
@@ -198,7 +194,7 @@ public class GemfireTemplate extends GemfireAccessor {
public <K, V> Map<K, V> getAll(final Collection<?> keys) { public <K, V> Map<K, V> getAll(final Collection<?> keys) {
return execute(new GemfireCallback<Map<K, V>>() { return execute(new GemfireCallback<Map<K, V>>() {
@SuppressWarnings("unchecked") @SuppressWarnings({ "unchecked", "rawtypes" })
public Map<K, V> doInGemfire(Region region) throws GemFireCheckedException, GemFireException { public Map<K, V> doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
return (Map<K, V>) region.getAll(keys); return (Map<K, V>) region.getAll(keys);
} }
@@ -207,7 +203,7 @@ public class GemfireTemplate extends GemfireAccessor {
public <K, V> void putAll(final Map<? extends K, ? extends V> map) { public <K, V> void putAll(final Map<? extends K, ? extends V> map) {
execute(new GemfireCallback<Object>() { execute(new GemfireCallback<Object>() {
@SuppressWarnings("unchecked") @SuppressWarnings({ "unchecked", "rawtypes" })
public Object doInGemfire(Region region) throws GemFireCheckedException, GemFireException { public Object doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
region.putAll(map); region.putAll(map);
return null; return null;
@@ -228,7 +224,7 @@ public class GemfireTemplate extends GemfireAccessor {
*/ */
public <E> SelectResults<E> query(final String query) { public <E> SelectResults<E> query(final String query) {
return execute(new GemfireCallback<SelectResults<E>>() { return execute(new GemfireCallback<SelectResults<E>>() {
@SuppressWarnings("unchecked") @SuppressWarnings({ "unchecked", "rawtypes" })
public SelectResults<E> doInGemfire(Region region) throws GemFireCheckedException, GemFireException { public SelectResults<E> doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
return region.query(query); return region.query(query);
} }
@@ -255,7 +251,7 @@ public class GemfireTemplate extends GemfireAccessor {
public <E> SelectResults<E> find(final String query, final Object... params) public <E> SelectResults<E> find(final String query, final Object... params)
throws InvalidDataAccessApiUsageException { throws InvalidDataAccessApiUsageException {
return execute(new GemfireCallback<SelectResults<E>>() { return execute(new GemfireCallback<SelectResults<E>>() {
@SuppressWarnings("unchecked") @SuppressWarnings({ "unchecked", "rawtypes" })
public SelectResults<E> doInGemfire(Region region) throws GemFireCheckedException, GemFireException { public SelectResults<E> doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
QueryService queryService = lookupQueryService(region); QueryService queryService = lookupQueryService(region);
Query q = queryService.newQuery(query); Query q = queryService.newQuery(query);
@@ -287,7 +283,7 @@ public class GemfireTemplate extends GemfireAccessor {
*/ */
public <T> T findUnique(final String query, final Object... params) throws InvalidDataAccessApiUsageException { public <T> T findUnique(final String query, final Object... params) throws InvalidDataAccessApiUsageException {
return execute(new GemfireCallback<T>() { return execute(new GemfireCallback<T>() {
@SuppressWarnings("unchecked") @SuppressWarnings({ "unchecked", "rawtypes" })
public T doInGemfire(Region region) throws GemFireCheckedException, GemFireException { public T doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
QueryService queryService = lookupQueryService(region); QueryService queryService = lookupQueryService(region);
Query q = queryService.newQuery(query); Query q = queryService.newQuery(query);

View File

@@ -23,6 +23,7 @@ import org.springframework.transaction.TransactionException;
* *
* @author Costin Leau * @author Costin Leau
*/ */
@SuppressWarnings("serial")
public class GemfireTransactionCommitException extends TransactionException { public class GemfireTransactionCommitException extends TransactionException {
public GemfireTransactionCommitException(String message, Throwable cause) { public GemfireTransactionCommitException(String message, Throwable cause) {

View File

@@ -64,6 +64,7 @@ import com.gemstone.gemfire.cache.Region;
*/ */
// TODO add lenient behavior if a transaction is already started on the current // TODO add lenient behavior if a transaction is already started on the current
// thread (what should happen then) // thread (what should happen then)
@SuppressWarnings("serial")
public class GemfireTransactionManager extends AbstractPlatformTransactionManager implements InitializingBean, public class GemfireTransactionManager extends AbstractPlatformTransactionManager implements InitializingBean,
ResourceTransactionManager { ResourceTransactionManager {
@@ -218,7 +219,7 @@ public class GemfireTransactionManager extends AbstractPlatformTransactionManage
*/ */
public <K, V> void setRegion(Region<K, V> region) { public <K, V> void setRegion(Region<K, V> region) {
Assert.notNull(region, "non-null arguments are required"); Assert.notNull(region, "non-null arguments are required");
this.cache = region.getCache(); this.cache = (Cache)region.getRegionService();
} }
/** /**
@@ -271,6 +272,7 @@ public class GemfireTransactionManager extends AbstractPlatformTransactionManage
private boolean rollbackOnly = false; private boolean rollbackOnly = false;
@SuppressWarnings("unused")
public boolean isRollbackOnly() { public boolean isRollbackOnly() {
return rollbackOnly; return rollbackOnly;
} }

View File

@@ -28,8 +28,13 @@ import com.gemstone.gemfire.cache.RegionService;
import com.gemstone.gemfire.cache.client.Pool; import com.gemstone.gemfire.cache.client.Pool;
import com.gemstone.gemfire.cache.client.PoolManager; import com.gemstone.gemfire.cache.client.PoolManager;
import com.gemstone.gemfire.cache.query.Index; import com.gemstone.gemfire.cache.query.Index;
import com.gemstone.gemfire.cache.query.IndexExistsException;
import com.gemstone.gemfire.cache.query.IndexInvalidException;
import com.gemstone.gemfire.cache.query.IndexNameConflictException;
import com.gemstone.gemfire.cache.query.IndexType; import com.gemstone.gemfire.cache.query.IndexType;
import com.gemstone.gemfire.cache.query.QueryService; import com.gemstone.gemfire.cache.query.QueryService;
import com.gemstone.gemfire.cache.query.RegionNotFoundException;
import com.springsource.vfabric.licensing.log.Logger;
/** /**
* Factory bean for easy declarative creation of GemFire Indexes. * Factory bean for easy declarative creation of GemFire Indexes.
@@ -71,7 +76,7 @@ public class IndexFactoryBean implements InitializingBean, BeanNameAware, Factor
index = createIndex(queryService, indexName); index = createIndex(queryService, indexName);
} }
private Index createIndex(QueryService queryService, String indexName) throws Exception { private Index createIndex(QueryService queryService, String indexName) throws Exception {
Collection<Index> indexes = queryService.getIndexes(); Collection<Index> indexes = queryService.getIndexes();
Index old = null; Index old = null;
@@ -95,13 +100,17 @@ public class IndexFactoryBean implements InitializingBean, BeanNameAware, Factor
} }
Index index = null; Index index = null;
try {
if (StringUtils.hasText(imports)) { if (StringUtils.hasText(imports)) {
index = queryService.createIndex(indexName, type, expression, from, imports); index = queryService.createIndex(indexName, type, expression, from, imports);
} }
else { else {
index = queryService.createIndex(indexName, type, expression, from); index = queryService.createIndex(indexName, type, expression, from);
} }
} catch (IndexExistsException e) {
// This is ok
}
return index; return index;
} }

View File

@@ -21,13 +21,14 @@ import java.lang.reflect.Field;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.DisposableBean; import org.springframework.beans.factory.DisposableBean;
import org.springframework.context.SmartLifecycle;
import org.springframework.core.io.Resource; import org.springframework.core.io.Resource;
import org.springframework.data.gemfire.client.ClientRegionFactoryBean; import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
import org.springframework.data.gemfire.wan.SmartLifecycleGatewaySender;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils; import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
import com.gemstone.gemfire.cache.asyncqueue.AsyncEventQueue;
import com.gemstone.gemfire.cache.AttributesFactory; import com.gemstone.gemfire.cache.AttributesFactory;
import com.gemstone.gemfire.cache.Cache; import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.CacheClosedException; import com.gemstone.gemfire.cache.CacheClosedException;
@@ -40,6 +41,7 @@ import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionAttributes; import com.gemstone.gemfire.cache.RegionAttributes;
import com.gemstone.gemfire.cache.RegionFactory; import com.gemstone.gemfire.cache.RegionFactory;
import com.gemstone.gemfire.cache.Scope; import com.gemstone.gemfire.cache.Scope;
import com.gemstone.gemfire.cache.asyncqueue.AsyncEventQueue;
import com.gemstone.gemfire.cache.wan.GatewaySender; import com.gemstone.gemfire.cache.wan.GatewaySender;
/** /**
@@ -55,7 +57,11 @@ import com.gemstone.gemfire.cache.wan.GatewaySender;
* @author Costin Leau * @author Costin Leau
* @author David Turanski * @author David Turanski
*/ */
public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> implements DisposableBean { public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> implements DisposableBean, SmartLifecycle {
private boolean autoStartup = true;
private boolean running;
protected final Log log = LogFactory.getLog(getClass()); protected final Log log = LogFactory.getLog(getClass());
@@ -150,13 +156,13 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
if (cacheWriter != null) { if (cacheWriter != null) {
regionFactory.setCacheWriter(cacheWriter); regionFactory.setCacheWriter(cacheWriter);
} }
if (diskStoreName != null) { if (diskStoreName != null) {
regionFactory.setDiskStoreName(diskStoreName); regionFactory.setDiskStoreName(diskStoreName);
Assert.isTrue(!isNotPersistent(),"it is invalid to specify a disk store if 'persistent' is set to false."); Assert.isTrue(!isNotPersistent(), "it is invalid to specify a disk store if 'persistent' is set to false.");
persistent = true; persistent = true;
} }
resolveDataPolicy(regionFactory, persistent, dataPolicy); resolveDataPolicy(regionFactory, persistent, dataPolicy);
if (scope != null) { if (scope != null) {
@@ -194,8 +200,7 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
if (dataPolicy == null) { if (dataPolicy == null) {
if (isPersistent()) { if (isPersistent()) {
regionFactory.setDataPolicy(DataPolicy.PERSISTENT_REPLICATE); regionFactory.setDataPolicy(DataPolicy.PERSISTENT_REPLICATE);
} } else {
else {
regionFactory.setDataPolicy(DataPolicy.DEFAULT); regionFactory.setDataPolicy(DataPolicy.DEFAULT);
} }
return; return;
@@ -238,23 +243,21 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
* @param region * @param region
*/ */
protected void postProcess(Region<K, V> region) { protected void postProcess(Region<K, V> region) {
// do nothing
} }
@Override @Override
public void destroy() throws Exception { public void destroy() throws Exception {
if (region != null) { if (region != null) {
if (close) { if (close) {
if (!region.getCache().isClosed()) { if (!region.getRegionService().isClosed()) {
try { try {
region.close(); region.close();
} } catch (CacheClosedException cce) {
catch (CacheClosedException cce) {
// nothing to see folks, move on. // nothing to see folks, move on.
} }
} }
} } else if (destroy) {
else if (destroy) {
region.destroyRegion(); region.destroyRegion();
} }
} }
@@ -414,4 +417,73 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
protected boolean isNotPersistent() { protected boolean isNotPersistent() {
return persistent != null && !persistent; return persistent != null && !persistent;
} }
/* (non-Javadoc)
* @see org.springframework.context.Lifecycle#start()
*/
@Override
public void start() {
if (!ObjectUtils.isEmpty(gatewaySenders)) {
synchronized (gatewaySenders) {
for (Object obj : gatewaySenders) {
SmartLifecycleGatewaySender gws = (SmartLifecycleGatewaySender) obj;
if (gws.isAutoStartup() && !gws.isRunning()) {
gws.start();
}
}
}
}
this.running = true;
}
/* (non-Javadoc)
* @see org.springframework.context.Lifecycle#stop()
*/
@Override
public void stop() {
if (!ObjectUtils.isEmpty(gatewaySenders)) {
synchronized (gatewaySenders) {
for (Object obj : gatewaySenders) {
SmartLifecycleGatewaySender gws = (SmartLifecycleGatewaySender) obj;
gws.stop();
}
}
}
this.running = false;
}
/* (non-Javadoc)
* @see org.springframework.context.Lifecycle#isRunning()
*/
@Override
public boolean isRunning() {
return this.running;
}
/* (non-Javadoc)
* @see org.springframework.context.Phased#getPhase()
*/
@Override
public int getPhase() {
return Integer.MAX_VALUE;
}
/* (non-Javadoc)
* @see org.springframework.context.SmartLifecycle#isAutoStartup()
*/
@Override
public boolean isAutoStartup() {
return this.autoStartup;
}
/* (non-Javadoc)
* @see org.springframework.context.SmartLifecycle#stop(java.lang.Runnable)
*/
@Override
public void stop(Runnable callback) {
stop();
callback.run();
}
} }

View File

@@ -19,6 +19,7 @@ package org.springframework.data.gemfire.client;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.util.List; import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.logging.Handler;
import org.springframework.beans.factory.BeanInitializationException; import org.springframework.beans.factory.BeanInitializationException;
import org.springframework.data.gemfire.CacheFactoryBean; import org.springframework.data.gemfire.CacheFactoryBean;
@@ -26,11 +27,15 @@ import org.springframework.data.gemfire.config.GemfireConstants;
import org.springframework.util.Assert; import org.springframework.util.Assert;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import com.gemstone.gemfire.LogWriter;
import com.gemstone.gemfire.cache.GemFireCache; import com.gemstone.gemfire.cache.GemFireCache;
import com.gemstone.gemfire.cache.client.ClientCacheFactory; import com.gemstone.gemfire.cache.client.ClientCacheFactory;
import com.gemstone.gemfire.cache.client.Pool; import com.gemstone.gemfire.cache.client.Pool;
import com.gemstone.gemfire.cache.client.PoolManager; import com.gemstone.gemfire.cache.client.PoolManager;
import com.gemstone.gemfire.distributed.DistributedSystem; import com.gemstone.gemfire.distributed.DistributedSystem;
import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
import com.gemstone.gemfire.i18n.LogWriterI18n;
import com.gemstone.gemfire.i18n.StringId;
import com.gemstone.gemfire.pdx.PdxSerializer; import com.gemstone.gemfire.pdx.PdxSerializer;
/** /**
@@ -103,16 +108,15 @@ public class ClientCacheFactoryBean extends CacheFactoryBean {
if (StringUtils.hasText(poolName)) { if (StringUtils.hasText(poolName)) {
p = PoolManager.find(poolName); p = PoolManager.find(poolName);
} }
// initialize a client-like Distributed System before initializing // Bind this client cache to a pool that hasn't been created yet.
// the pool
// initialize a client-like Distributed System before initializing
// the pool
if (p == null) { if (p == null) {
Properties prop = mergeProperties(); PoolFactoryBean.connectToTemporaryDs();
prop.setProperty("mcast-port", "0");
prop.setProperty("locators", "");
DistributedSystem system = DistributedSystem.connect(prop);
} }
if (StringUtils.hasText(poolName)) { if (StringUtils.hasText(poolName)) {
try { try {
@@ -134,6 +138,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean {
p = getBeanFactory().getBean(Pool.class); p = getBeanFactory().getBean(Pool.class);
this.poolName = p.getName(); this.poolName = p.getName();
} }
} }
if (p != null) { if (p != null) {
@@ -167,7 +172,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean {
} }
List<InetSocketAddress> servers = p.getServers(); List<InetSocketAddress> servers = p.getServers();
if (locators != null) { if (servers != null) {
for (InetSocketAddress inet : servers) { for (InetSocketAddress inet : servers) {
ccf.addPoolServer(inet.getHostName(), inet.getPort()); ccf.addPoolServer(inet.getHostName(), inet.getPort());
} }

View File

@@ -1,58 +0,0 @@
/*
* Copyright 2010-2012 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.client;
/**
* Simple holder class used for configuring servers or locators for GemFire pools.
*
* @see com.gemstone.gemfire.cache.client.PoolFactory
*
* @author Costin Leau
*/
public class PoolConnection {
private String host;
private int port;
/**
* @return the host
*/
public String getHost() {
return host;
}
/**
* @param host the host to set
*/
public void setHost(String host) {
this.host = host;
}
/**
* @return the port
*/
public int getPort() {
return port;
}
/**
* @param port the port to set
*/
public void setPort(int port) {
this.port = port;
}
}

View File

@@ -17,6 +17,7 @@
package org.springframework.data.gemfire.client; package org.springframework.data.gemfire.client;
import java.util.Collection; import java.util.Collection;
import java.util.Properties;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@@ -34,7 +35,9 @@ import com.gemstone.gemfire.cache.GemFireCache;
import com.gemstone.gemfire.cache.client.Pool; import com.gemstone.gemfire.cache.client.Pool;
import com.gemstone.gemfire.cache.client.PoolFactory; import com.gemstone.gemfire.cache.client.PoolFactory;
import com.gemstone.gemfire.cache.client.PoolManager; import com.gemstone.gemfire.cache.client.PoolManager;
import com.gemstone.gemfire.distributed.DistributedSystem;
import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem; import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
import java.net.InetSocketAddress;
/** /**
* Factory bean for easy declaration and configuration of a GemFire pool. If a * Factory bean for easy declaration and configuration of a GemFire pool. If a
@@ -63,8 +66,8 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean,
// pool settings // pool settings
private String beanName; private String beanName;
private String name; private String name;
private Collection<PoolConnection> locators; private Collection<InetSocketAddress> locators;
private Collection<PoolConnection> servers; private Collection<InetSocketAddress> servers;
private BeanFactory beanFactory; private BeanFactory beanFactory;
@@ -109,8 +112,8 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean,
// eagerly initialize cache (if needed) // eagerly initialize cache (if needed)
if (InternalDistributedSystem.getAnyInstance() == null) { if (InternalDistributedSystem.getAnyInstance() == null) {
// no cache found, do eager initialization // no cache found, create a temp connection
beanFactory.getBean(GemFireCache.class); connectToTemporaryDs();
} }
// first check the configured pools // first check the configured pools
@@ -137,15 +140,15 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean,
PoolFactory poolFactory = PoolManager.createFactory(); PoolFactory poolFactory = PoolManager.createFactory();
if (!CollectionUtils.isEmpty(locators)) { if (!CollectionUtils.isEmpty(locators)) {
for (PoolConnection connection : locators) { for (InetSocketAddress connection : locators) {
poolFactory.addLocator(connection.getHost(), poolFactory.addLocator(connection.getHostName(),
connection.getPort()); connection.getPort());
} }
} }
if (!CollectionUtils.isEmpty(servers)) { if (!CollectionUtils.isEmpty(servers)) {
for (PoolConnection connection : servers) { for (InetSocketAddress connection : servers) {
poolFactory.addServer(connection.getHost(), poolFactory.addServer(connection.getHostName(),
connection.getPort()); connection.getPort());
} }
} }
@@ -209,7 +212,7 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean,
* @param locators * @param locators
* the locators to set * the locators to set
*/ */
public void setLocators(Collection<PoolConnection> locators) { public void setLocators(Collection<InetSocketAddress> locators) {
this.locators = locators; this.locators = locators;
} }
@@ -217,7 +220,7 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean,
* @param servers * @param servers
* the servers to set * the servers to set
*/ */
public void setServers(Collection<PoolConnection> servers) { public void setServers(Collection<InetSocketAddress> servers) {
this.servers = servers; this.servers = servers;
} }
@@ -377,4 +380,16 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean,
public void setPrSingleHopEnabled(boolean prSingleHopEnabled) { public void setPrSingleHopEnabled(boolean prSingleHopEnabled) {
this.prSingleHopEnabled = prSingleHopEnabled; this.prSingleHopEnabled = prSingleHopEnabled;
} }
/*
* A work around to create a pool if no cache has been created yet
* initialize a client-like Distributed System before initializing
* the pool
*/
static void connectToTemporaryDs() {
Properties prop = new Properties();
prop.setProperty("mcast-port", "0");
prop.setProperty("locators", "");
DistributedSystem.connect(prop);
}
} }

View File

@@ -19,11 +19,10 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser; import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext; import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.gemfire.wan.AsyncEventQueueFactoryBean; import org.springframework.data.gemfire.wan.AsyncEventQueueFactoryBean;
import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils; import org.springframework.util.xml.DomUtils;
import org.w3c.dom.Element; import org.w3c.dom.Element;
import com.gemstone.gemfire.internal.lang.StringUtils;
/** /**
* @author David Turanski * @author David Turanski
* *
@@ -41,8 +40,10 @@ public class AsyncEventQueueParser extends AbstractSingleBeanDefinitionParser {
Element asyncEventListenerElement = DomUtils.getChildElementByTagName(element, "async-event-listener"); Element asyncEventListenerElement = DomUtils.getChildElementByTagName(element, "async-event-listener");
Object asyncEventListener = ParsingUtils.parseRefOrSingleNestedBeanDeclaration(parserContext, Object asyncEventListener = ParsingUtils.parseRefOrSingleNestedBeanDeclaration(parserContext,
asyncEventListenerElement, builder); asyncEventListenerElement, builder);
String cacheName = StringUtils.isEmpty(element.getAttribute("cache-ref")) ? "gemfireCache" : element
.getAttribute("cache-ref"); String cacheName = !StringUtils.hasText(element.getAttribute("cache-ref")) ? GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME
: element.getAttribute("cache-ref");
builder.addConstructorArgReference(cacheName); builder.addConstructorArgReference(cacheName);
builder.addConstructorArgValue(asyncEventListener); builder.addConstructorArgValue(asyncEventListener);
ParsingUtils.setPropertyValue(element, builder, "batch-size"); ParsingUtils.setPropertyValue(element, builder, "batch-size");
@@ -50,5 +51,23 @@ public class AsyncEventQueueParser extends AbstractSingleBeanDefinitionParser {
ParsingUtils.setPropertyValue(element, builder, "disk-store-ref"); ParsingUtils.setPropertyValue(element, builder, "disk-store-ref");
ParsingUtils.setPropertyValue(element, builder, "persistent"); ParsingUtils.setPropertyValue(element, builder, "persistent");
ParsingUtils.setPropertyValue(element, builder, "parallel"); ParsingUtils.setPropertyValue(element, builder, "parallel");
ParsingUtils.setPropertyValue(element, builder, NAME_ATTRIBUTE);
if (!StringUtils.hasText(element.getAttribute(NAME_ATTRIBUTE))) {
if (element.getParentNode().getNodeName().endsWith("region")) {
Element region = (Element) element.getParentNode();
String regionName = StringUtils.hasText(region.getAttribute("name")) ? region.getAttribute("name")
: region.getAttribute("id");
int i = 0;
String name = regionName + ".asyncEventQueue#" + i;
while (parserContext.getRegistry().isBeanNameInUse(name)) {
i++;
name = regionName + ".asyncEventQueue#" + i;
}
builder.addPropertyValue("name", name);
}
}
} }
} }

View File

@@ -19,6 +19,7 @@ package org.springframework.data.gemfire.config;
import java.util.List; import java.util.List;
import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.beans.factory.BeanDefinitionStoreException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.ManagedList;
@@ -26,6 +27,7 @@ import org.springframework.beans.factory.support.ManagedMap;
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser; import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext; import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.gemfire.CacheFactoryBean; import org.springframework.data.gemfire.CacheFactoryBean;
import org.springframework.data.gemfire.GemfireBeanPostProcessor;
import org.springframework.util.CollectionUtils; import org.springframework.util.CollectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils; import org.springframework.util.xml.DomUtils;
@@ -52,6 +54,9 @@ class CacheParser extends AbstractSimpleBeanDefinitionParser {
@Override @Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
super.doParse(element, builder); super.doParse(element, builder);
// BeanDefinition gemfirePostProcessor = BeanDefinitionBuilder.genericBeanDefinition(GemfireBeanPostProcessor.class).getBeanDefinition();
// parserContext.getRegistry().registerBeanDefinition(GemfireBeanPostProcessor.class.getName(), gemfirePostProcessor);
ParsingUtils.setPropertyValue(element, builder, "cache-xml-location", "cacheXml"); ParsingUtils.setPropertyValue(element, builder, "cache-xml-location", "cacheXml");
ParsingUtils.setPropertyReference(element, builder, "properties-ref", "properties"); ParsingUtils.setPropertyReference(element, builder, "properties-ref", "properties");

View File

@@ -37,7 +37,7 @@ class ClientCacheParser extends CacheParser {
@Override @Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
super.doParse(element, parserContext, builder); super.doParse(element, parserContext, builder);
ParsingUtils.setPropertyValue(element, builder, "pool-name"); //ParsingUtils.setPropertyValue(element, builder, "pool-name","poolName",GemfireConstants.DEFAULT_GEMFIRE_POOL_NAME);
} }
@Override @Override

View File

@@ -36,10 +36,12 @@ class GatewaySenderParser extends AbstractSimpleBeanDefinitionParser {
@Override @Override
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) { protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
builder.setLazyInit(false);
String cacheRef = element.getAttribute("cache-ref"); String cacheRef = element.getAttribute("cache-ref");
// add cache reference (fallback to default if nothing is specified) // add cache reference (fallback to default if nothing is specified)
builder.addConstructorArgReference((StringUtils.hasText(cacheRef) ? cacheRef : "gemfireCache")); builder.addConstructorArgReference((StringUtils.hasText(cacheRef) ? cacheRef
: GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME));
ParsingUtils.setPropertyValue(element, builder, "alert-threshold"); ParsingUtils.setPropertyValue(element, builder, "alert-threshold");
ParsingUtils.setPropertyValue(element, builder, "batch-size"); ParsingUtils.setPropertyValue(element, builder, "batch-size");
ParsingUtils.setPropertyValue(element, builder, "batch-time-interval"); ParsingUtils.setPropertyValue(element, builder, "batch-time-interval");
@@ -55,6 +57,7 @@ class GatewaySenderParser extends AbstractSimpleBeanDefinitionParser {
ParsingUtils.setPropertyValue(element, builder, "socket-read-timeout"); ParsingUtils.setPropertyValue(element, builder, "socket-read-timeout");
ParsingUtils.setPropertyValue(element, builder, "persistent"); ParsingUtils.setPropertyValue(element, builder, "persistent");
ParsingUtils.setPropertyValue(element, builder, "parallel"); ParsingUtils.setPropertyValue(element, builder, "parallel");
ParsingUtils.setPropertyValue(element, builder, NAME_ATTRIBUTE);
Element eventFilterElement = DomUtils.getChildElementByTagName(element, "event-filter"); Element eventFilterElement = DomUtils.getChildElementByTagName(element, "event-filter");
if (eventFilterElement != null) { if (eventFilterElement != null) {
@@ -63,5 +66,25 @@ class GatewaySenderParser extends AbstractSimpleBeanDefinitionParser {
} }
ParsingUtils.parseTransportFilters(element, parserContext, builder); ParsingUtils.parseTransportFilters(element, parserContext, builder);
/**
* set the name for an inner bean
*/
if (!StringUtils.hasText(element.getAttribute(NAME_ATTRIBUTE))) {
if (element.getParentNode().getNodeName().endsWith("region")) {
Element region = (Element) element.getParentNode();
String regionName = StringUtils.hasText(region.getAttribute("name")) ? region.getAttribute("name")
: region.getAttribute("id");
int i = 0;
String name = regionName + ".gatewaySender#" + i;
while (parserContext.getRegistry().isBeanNameInUse(name)) {
i++;
name = regionName + ".gatewaySender#" + i;
}
builder.addPropertyValue("name", name);
}
}
} }
} }

View File

@@ -16,6 +16,7 @@
package org.springframework.data.gemfire.config; package org.springframework.data.gemfire.config;
import java.net.InetSocketAddress;
import java.util.List; import java.util.List;
import org.springframework.beans.factory.BeanDefinitionStoreException; import org.springframework.beans.factory.BeanDefinitionStoreException;
@@ -25,7 +26,6 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.ManagedList; import org.springframework.beans.factory.support.ManagedList;
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser; import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
import org.springframework.beans.factory.xml.ParserContext; import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.data.gemfire.client.PoolConnection;
import org.springframework.data.gemfire.client.PoolFactoryBean; import org.springframework.data.gemfire.client.PoolFactoryBean;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import org.springframework.util.xml.DomUtils; import org.springframework.util.xml.DomUtils;
@@ -35,13 +35,16 @@ import org.w3c.dom.Element;
* Parser for &lt;pool;gt; definitions. * Parser for &lt;pool;gt; definitions.
* *
* @author Costin Leau * @author Costin Leau
* @author David Turanski
*/ */
class PoolParser extends AbstractSimpleBeanDefinitionParser { class PoolParser extends AbstractSimpleBeanDefinitionParser {
@Override
protected Class<?> getBeanClass(Element element) { protected Class<?> getBeanClass(Element element) {
return PoolFactoryBean.class; return PoolFactoryBean.class;
} }
@Override
protected void postProcess(BeanDefinitionBuilder builder, Element element) { protected void postProcess(BeanDefinitionBuilder builder, Element element) {
List<Element> subElements = DomUtils.getChildElements(element); List<Element> subElements = DomUtils.getChildElements(element);
ManagedList<Object> locators = new ManagedList<Object>(subElements.size()); ManagedList<Object> locators = new ManagedList<Object>(subElements.size());
@@ -77,9 +80,9 @@ class PoolParser extends AbstractSimpleBeanDefinitionParser {
} }
private BeanDefinition parseConnection(Element element) { private BeanDefinition parseConnection(Element element) {
BeanDefinitionBuilder defBuilder = BeanDefinitionBuilder.genericBeanDefinition(PoolConnection.class); BeanDefinitionBuilder defBuilder = BeanDefinitionBuilder.genericBeanDefinition(InetSocketAddress.class);
ParsingUtils.setPropertyValue(element, defBuilder, "host", "host"); defBuilder.addConstructorArgValue(element.getAttribute("host"));
ParsingUtils.setPropertyValue(element, defBuilder, "port", "port"); defBuilder.addConstructorArgValue(element.getAttribute("port"));
return defBuilder.getBeanDefinition(); return defBuilder.getBeanDefinition();
} }

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2002-2012 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.function;
import com.gemstone.gemfire.cache.execute.FunctionContext;
/**
* @author David Turanski
*
*/
public class DefaultFunctionArgumentResolver implements FunctionArgumentResolver {
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.FunctionArgumentResolver#resolveFunctionArguments(com.gemstone.gemfire.cache.execute.FunctionContext)
*/
@Override
public Object[] resolveFunctionArguments(FunctionContext functionContext) {
Object[] args = (functionContext.getArguments().getClass().isArray()) ? (Object[]) functionContext
.getArguments() : new Object[] { functionContext.getArguments() };
return args;
}
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright 2002-2012 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.function;
import com.gemstone.gemfire.cache.execute.FunctionContext;
/**
* Strategy Interface for resolving function invocation arguments, given a {@link FunctionContext}
* @author David Turanski
*
*/
public interface FunctionArgumentResolver {
public Object[] resolveFunctionArguments(FunctionContext functionContext);
}

View File

@@ -0,0 +1,140 @@
/*
* Copyright 2002-2012 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.function;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.data.gemfire.function.config.Filter;
import org.springframework.data.gemfire.function.config.GemfireFunctionUtils;
import org.springframework.data.gemfire.function.config.RegionData;
import org.springframework.data.gemfire.util.ArrayUtils;
import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.execute.FunctionContext;
import com.gemstone.gemfire.cache.execute.RegionFunctionContext;
import com.gemstone.gemfire.cache.partition.PartitionRegionHelper;
/**
* @author David Turanski
*
*/
public class FunctionContextInjectingArgumentResolver extends DefaultFunctionArgumentResolver {
private static Log logger = LogFactory.getLog(FunctionContextInjectingArgumentResolver.class);
private final int regionParameterPosition;
private final int filterParameterPosition;
private final int functionContextParameterPosition;
private final Method method;
public FunctionContextInjectingArgumentResolver(Method method) {
this.method = method;
int annotatedRegionDataParameterPosition = GemfireFunctionUtils.getAnnotationParameterPosition(method, RegionData.class, new Class[]{Map.class});
int regionTypeParameterPosition = getArgumentTypePosition(method,Region.class);
if (annotatedRegionDataParameterPosition >=0 && regionTypeParameterPosition >= 0) {
Assert.isTrue(annotatedRegionDataParameterPosition == regionTypeParameterPosition,
String.format("Function method signature for method %s cannot contain an @RegionData parameter and a different Region type parameter", method.getName()));
}
int tempRegionParameterPosition = -1;
if (annotatedRegionDataParameterPosition >=0 ) {
tempRegionParameterPosition = annotatedRegionDataParameterPosition;
} else if (regionTypeParameterPosition >=0) {
tempRegionParameterPosition = regionTypeParameterPosition;
}
regionParameterPosition = tempRegionParameterPosition;
filterParameterPosition = GemfireFunctionUtils.getAnnotationParameterPosition(method, Filter.class, new Class[]{Set.class});
functionContextParameterPosition = getArgumentTypePosition(method,FunctionContext.class);
if (regionParameterPosition >=0 && filterParameterPosition >=0) {
Assert.state(regionParameterPosition != filterParameterPosition, "region parameter and filter parameter must be different");
}
}
@Override
public Object[] resolveFunctionArguments(FunctionContext functionContext) {
Object[] args = super.resolveFunctionArguments(functionContext);
if (functionContext instanceof RegionFunctionContext) {
if (this.regionParameterPosition >= 0) {
args = ArrayUtils.insert(args, regionParameterPosition, getRegionForContext((RegionFunctionContext)functionContext));
}
if (this.filterParameterPosition >= 0) {
args = ArrayUtils.insert(args, filterParameterPosition, ((RegionFunctionContext)functionContext).getFilter());
}
if (this.functionContextParameterPosition >= 0) {
args = ArrayUtils.insert(args, functionContextParameterPosition, functionContext);
}
}
Assert.isTrue(args.length == method.getParameterTypes().length,
String.format("wrong number of arguments for method %s. Expected :%d, actual: %d", method.getName(),
method.getParameterTypes().length, args.length));
return args;
}
/*
* @param regionFunctionContext
* @return
*/
private static Region<?, ?> getRegionForContext(RegionFunctionContext regionFunctionContext) {
Region<?, ?> region = regionFunctionContext.getDataSet();
if (PartitionRegionHelper.isPartitionedRegion(region)) {
if (logger.isDebugEnabled()) {
logger.debug("this is a partitioned region - filtering local data for context");
}
region = PartitionRegionHelper.getLocalDataForContext(regionFunctionContext);
}
if (logger.isDebugEnabled()) {
logger.debug("region contains " + region.size() + " items");
}
return region;
}
private static int getArgumentTypePosition(Method method, Class<?> requiredType) {
int position = -1;
int i = 0;
for (Class<?> clazz: method.getParameterTypes()) {
if (requiredType.equals(clazz)) {
Assert.state(position < 0, String.format("Method %s signature cannot contain more than one parameter of type %s."
,method.getName(),requiredType.getName()));
position = i;
}
i++;
}
return position;
}
}

View File

@@ -1,46 +0,0 @@
/*
* Copyright 2002-2011 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.function;
import java.io.Serializable;
import java.util.List;
import java.util.Set;
import com.gemstone.gemfire.cache.execute.Function;
/**
* @author David Turanski
*
* @param <T>
*/
public interface GemfireFunctionOperations<T> {
public abstract List<T> executeOnRegion(Function function, String regionId, Serializable... args);
public abstract T executeOnRegionAndExtract(Function function, String regionId, Serializable... args);
public abstract List<T> executeOnRegion(Function function, String regionId, Set<?> keys, Serializable... args);
public abstract List<T> executeOnRegion(String functionId, String regionId, Serializable... args);
public abstract List<T> executeOnRegion(String functionId, String regionId, Set<?> keys, Serializable... args);
public abstract T executeOnRegion(String regionId, GemfireFunctionCallback<T> callback);
public abstract List<T> executeOnServers(Function function, Serializable... args);
public abstract List<T> executeOnServers(String functionId, Serializable... args);
public abstract T executeOnServers(GemfireFunctionCallback<T> callback);
}

View File

@@ -1,250 +0,0 @@
/*
* Copyright 2002-2011 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.function;
import java.io.Serializable;
import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Set;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import com.gemstone.gemfire.cache.execute.FunctionException;
/**
* Creates a Proxy to a delegate that is executed as a Gemfire remote function
* using {@link MethodInvokingFunction}. Also, adds the {@link FilterAware}
*
* interface to the proxy which is used to set a data filter when execution is
* performed on a partitioned region.
*
* @author David Turanski
*
*/
public class GemfireFunctionProxyFactoryBean implements FactoryBean<Object>, MethodInterceptor, BeanClassLoaderAware {
private volatile ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
private final Class<?> serviceInterface;
private volatile Object serviceProxy;
private volatile boolean initialized;
private final String delegateClassName;
private final ThreadLocal<Set<? extends Serializable>> filter;
private boolean methodInvokingFunctionRegistered;
private volatile String regionName;
private final GemfireFunctionOperations<?> gemfireFunctionOperations;
private static Log logger = LogFactory.getLog(GemfireFunctionProxyFactoryBean.class);
/**
*
* @param serviceInterface the proxy interface
* @param delegateClassName the name of the implementation class
* @param gemfireFunctionOperations a strategy interface, normally a
* {@link GemfireFunctionTemplate}
*/
public GemfireFunctionProxyFactoryBean(Class<?> serviceInterface, String delegateClassName,
GemfireFunctionOperations<?> gemfireFunctionOperations) {
this.delegateClassName = delegateClassName;
Assert.notNull(serviceInterface, "'serviceInterface' must not be null");
Assert.isTrue(serviceInterface.isInterface(), "'serviceInterface' must be an interface");
this.serviceInterface = serviceInterface;
Assert.notNull(gemfireFunctionOperations);
this.gemfireFunctionOperations = gemfireFunctionOperations;
this.filter = new ThreadLocal<Set<? extends Serializable>>();
}
// @Override
public void setBeanClassLoader(ClassLoader classLoader) {
beanClassLoader = classLoader;
}
// @Override
@SuppressWarnings("unchecked")
public Object invoke(MethodInvocation invocation) throws Throwable {
if (AopUtils.isToStringMethod(invocation.getMethod())) {
return "Gemfire function proxy for service interface [" + this.serviceInterface + "]";
}
if (logger.isDebugEnabled()) {
logger.debug("invoking method " + invocation.getMethod().getName());
}
if (isSetFilterMethod(invocation.getMethod())) {
setFilter((Set<? extends Serializable>) invocation.getArguments()[0]);
return getObject();
}
RemoteMethodInvocation remoteInvocation = new RemoteMethodInvocation(this.delegateClassName, invocation
.getMethod().getName(), convertArgsToSerializable(invocation.getArguments()));
List<?> results = null;
if (this.methodInvokingFunctionRegistered) {
if (this.regionName != null) {
results = this.gemfireFunctionOperations.executeOnRegion(MethodInvokingFunction.FUNCTION_ID,
this.regionName, this.getFilter(), remoteInvocation);
}
else {
if (this.getFilter() != null) {
logger.warn("No region is specified. Filter has no effect on a data independent function execution");
}
results = this.gemfireFunctionOperations.executeOnServers(MethodInvokingFunction.FUNCTION_ID,
remoteInvocation);
}
}
else {
if (this.regionName != null) {
results = this.gemfireFunctionOperations.executeOnRegion(new MethodInvokingFunction(), this.regionName,
this.getFilter(), remoteInvocation);
}
else {
if (this.getFilter() != null) {
logger.warn("No region is specified. Filter has no effect on a data independent function execution");
}
results = this.gemfireFunctionOperations.executeOnServers(new MethodInvokingFunction(),
remoteInvocation);
}
}
return extractResult(results, invocation.getMethod().getReturnType());
}
// @Override
public Object getObject() throws Exception {
if (this.serviceProxy == null) {
this.onInit();
Assert.notNull(this.serviceProxy, "failed to initialize proxy");
}
return this.serviceProxy;
}
// @Override
public Class<?> getObjectType() {
return (this.serviceInterface != null ? this.serviceInterface : null);
}
// @Override
public boolean isSingleton() {
return true;
}
protected Set<?> getFilter() {
return filter.get();
}
protected void setFilter(Set<? extends Serializable> filter) {
this.filter.set(filter);
}
/**
* Set to true id {@link MethodInvokingFunction} is a registered function.
* If registered, invocations will not create and transport a new instance
* of the function to the cache server(s).
* @param methodInvokingFunctionRegistered
*/
public void setMethodInvokingFunctionRegistered(boolean methodInvokingFunctionRegistered) {
this.methodInvokingFunctionRegistered = methodInvokingFunctionRegistered;
}
/**
*
* Optional region to use. If set, the function will execute onRegion, if
* null the function will execute onServers
*
* @param regionName
*/
public void setRegionName(String regionName) {
this.regionName = regionName;
}
// TODO: Use something like cglib to implement setFilter() directly
// to eliminate the need to cast the proxy to FilterAware
protected void onInit() {
if (this.initialized) {
return;
}
ProxyFactory proxyFactory = new ProxyFactory(serviceInterface, this);
proxyFactory.addInterface(FilterAware.class);
this.serviceProxy = proxyFactory.getProxy(this.beanClassLoader);
this.initialized = true;
}
/*
* This tweek is needed to prevent an argument mismatch on the function
* invocation.
*/
private Serializable[] convertArgsToSerializable(Object[] array) {
return Arrays.copyOf(array, array.length, Serializable[].class);
}
/*
* Match the result to the declared return type
*/
private Object extractResult(List<?> results, Class<?> returnType) {
Object result = null;
if (List.class.isAssignableFrom(returnType)) {
result = results;
}
else {
int nonNullItems = 0;
for (Object obj : results) {
if (obj != null) {
if (++nonNullItems > 1) {
throw new FunctionException("multiple results found for single valued return type");
}
else {
result = obj;
}
}
}
}
if (logger.isDebugEnabled()) {
logger.debug("returning result as " + result.getClass().getName());
}
return result;
}
private static boolean isSetFilterMethod(Method method) {
try {
Method setFilterMethod = FilterAware.class.getMethod("setFilter", Set.class);
return method.equals(setFilterMethod);
}
catch (SecurityException e) {
}
catch (NoSuchMethodException e) {
}
return false;
}
}

View File

@@ -1,168 +0,0 @@
/*
* Copyright 2002-2011 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.function;
import java.io.Serializable;
import java.util.List;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionService;
import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.Function;
import com.gemstone.gemfire.cache.execute.FunctionService;
/**
* @author David Turanski
*
*/
public class GemfireFunctionTemplate<T> implements InitializingBean, GemfireFunctionOperations<T> {
/** Logger available to subclasses */
protected final Log log = LogFactory.getLog(getClass());
private RegionService cache;
private long timeout;
/**
*
* @param cache
*/
public GemfireFunctionTemplate (RegionService cache) {
this.cache = cache;
afterPropertiesSet();
}
public void afterPropertiesSet() {
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.GemfireFunctionOperations#executeOnRegion(com.gemstone.gemfire.cache.execute.Function, java.lang.String, java.io.Serializable)
*/
public List<T> executeOnRegion(Function function, String regionId, Serializable... args) {
Region<?,?> region = getRegion(regionId);
Assert.notNull(region,"Region '" + regionId + "' not found");
RegionFunctionExecution<T> execution = new RegionFunctionExecution<T>(region, function, args);
execution.setTimeout(this.timeout);
return execution.execute();
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.GemfireFunctionOperations#executeOnRegionAndExtract(com.gemstone.gemfire.cache.execute.Function, java.lang.String, java.io.Serializable)
*/
public T executeOnRegionAndExtract(Function function, String regionId, Serializable... args) {
Region<?,?> region = getRegion(regionId);
Assert.notNull(region,"Region '" + regionId + "' not found");
RegionFunctionExecution<T> execution = new RegionFunctionExecution<T>(region, function, args);
execution.setTimeout(this.timeout);
return execution.executeAndExtract();
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.GemfireFunctionOperations#executeOnRegion(com.gemstone.gemfire.cache.execute.Function, java.lang.String, java.util.Set, java.io.Serializable)
*/
public List<T> executeOnRegion(Function function, String regionId, Set<?> keys, Serializable... args) {
Region<?,?> region = getRegion(regionId);
Assert.notNull(region,"Region '" + regionId + "' not found");
RegionFunctionExecution<T> execution = new RegionFunctionExecution<T>(region, function, args);
execution.setKeys(keys);
execution.setTimeout(this.timeout);
return execution.execute();
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.GemfireFunctionOperations#executeOnRegion(java.lang.String, java.lang.String, java.io.Serializable)
*/
public List<T> executeOnRegion(String functionId, String regionId, Serializable... args) {
Region<?,?> region = getRegion(regionId);
Assert.notNull(region,"Region '" + regionId + "' not found");
RegionFunctionExecution<T> execution = new RegionFunctionExecution<T>(region, functionId, args);
execution.setTimeout(this.timeout);
return execution.execute();
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.GemfireFunctionOperations#executeOnRegion(java.lang.String, java.lang.String, java.util.Set, java.io.Serializable)
*/
public List<T> executeOnRegion(String functionId, String regionId, Set<?> keys, Serializable... args) {
Region<?,?> region = getRegion(regionId);
Assert.notNull(region,"Region '" + regionId + "' not found");
RegionFunctionExecution<T> execution = new RegionFunctionExecution<T>(region, functionId, args);
execution.setKeys(keys);
execution.setTimeout(this.timeout);
return execution.execute();
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.GemfireFunctionOperations#executeOnRegion(java.lang.String, org.springframework.data.gemfire.function.GemfireFunctionCallback)
*/
public T executeOnRegion(String regionId, GemfireFunctionCallback<T> callback ) {
Region<?,?> region = getRegion(regionId);
Assert.notNull(region,"Region '" + regionId + "' not found");
Execution execution = FunctionService.onRegion(region);
return callback.doInGemfire(execution);
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.GemfireFunctionOperations#executeOnServers(com.gemstone.gemfire.cache.execute.Function, java.io.Serializable)
*/
public List<T> executeOnServers(Function function, Serializable... args) {
ServersFunctionExecution<T> execution = new ServersFunctionExecution<T>(this.cache, function, args);
execution.setTimeout(this.timeout);
return execution.execute();
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.GemfireFunctionOperations#executeOnServers(java.lang.String, java.io.Serializable)
*/
public List<T> executeOnServers(String functionId, Serializable... args) {
ServersFunctionExecution<T> execution = new ServersFunctionExecution<T>(this.cache, functionId, args);
execution.setTimeout(this.timeout);
return execution.execute();
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.GemfireFunctionOperations#executeOnServers(org.springframework.data.gemfire.function.GemfireFunctionCallback)
*/
public T executeOnServers(GemfireFunctionCallback<T> callback ) {
Execution execution = FunctionService.onServers(this.cache);
return callback.doInGemfire(execution);
}
public Region<?,?> getRegion(String regionId) {
return this.cache.getRegion(regionId);
}
public void setTimeout(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}

View File

@@ -1,51 +0,0 @@
/*
* Copyright 2002-2011 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.function;
import java.io.Serializable;
import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.Function;
import com.gemstone.gemfire.cache.execute.FunctionService;
import com.gemstone.gemfire.distributed.DistributedSystem;
/**
* @author David Turanski
*
*/
public class MemberFunctionExecution extends FunctionExecution<Object> {
private final DistributedSystem distributedSystem;
/**
* @param functionId
* @param args
*/
public MemberFunctionExecution(DistributedSystem distributedSystem, Function function, Serializable... args) {
super(function, args);
this.distributedSystem = distributedSystem;
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.FunctionExecution#getExecution()
*/
@Override
protected Execution getExecution() {
return FunctionService.onMember(this.distributedSystem, this.distributedSystem.getDistributedMember());
}
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2011 the original author or authors. * Copyright 2002-2012 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 * 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 * the License. You may obtain a copy of the License at

View File

@@ -12,11 +12,10 @@
*/ */
package org.springframework.data.gemfire.function; package org.springframework.data.gemfire.function;
import java.io.Serializable;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Arrays; import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.Set;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@@ -25,23 +24,21 @@ import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils; import org.springframework.util.StringUtils;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.execute.Function; import com.gemstone.gemfire.cache.execute.Function;
import com.gemstone.gemfire.cache.execute.FunctionContext; import com.gemstone.gemfire.cache.execute.FunctionContext;
import com.gemstone.gemfire.cache.execute.RegionFunctionContext;
import com.gemstone.gemfire.cache.execute.ResultSender; import com.gemstone.gemfire.cache.execute.ResultSender;
import com.gemstone.gemfire.cache.partition.PartitionRegionHelper;
import com.gemstone.gemfire.internal.util.ArrayUtils;
/** /**
* Invokes a POJO's given method as a Gemfire remote function. * Invokes a POJO's given method as a Gemfire remote function.
* If the POJO has a constructor that takes a Map, and the function context is Region, the * If the POJO has a constructor that takes a Map, and the function context is Region, the
* region will be injected. The delegate class name, the method name, and the method arguments * region will be injected. The delegate class name, the method name, and the method arguments
* are part of a remote function invocation, therefore all arguments must be serializable. * are part of a remote function invocation, therefore all arguments must be serializable
* or an alternate serialization method must be used.
* The delegate class must be the class path of the remote cache(s) * The delegate class must be the class path of the remote cache(s)
* @author David Turanski * @author David Turanski
* *
*/ */
@SuppressWarnings("serial") @SuppressWarnings("serial")
public class PojoFunctionWrapper implements Function { public class PojoFunctionWrapper implements Function {
@@ -53,9 +50,13 @@ public class PojoFunctionWrapper implements Function {
private final Object target; private final Object target;
private final Method method; private final Method method;
private final String id; private final String id;
private volatile Integer regionParameterPosition;
private final FunctionArgumentResolver functionArgumentResolver;
public PojoFunctionWrapper(Object target, Method method, String id) { public PojoFunctionWrapper(Object target, Method method, String id) {
this.functionArgumentResolver = new FunctionContextInjectingArgumentResolver(method);
this.id = StringUtils.hasText(id) ? id : ClassUtils.getQualifiedMethodName(method); this.id = StringUtils.hasText(id) ? id : ClassUtils.getQualifiedMethodName(method);
this.target = target; this.target = target;
this.method = method; this.method = method;
@@ -95,31 +96,13 @@ public class PojoFunctionWrapper implements Function {
this.optimizeForWrite = optimizeForWrite; this.optimizeForWrite = optimizeForWrite;
} }
public void setRegionParameterPosition(int regionParameterPosition) {
this.regionParameterPosition = regionParameterPosition;
}
//@Override //@Override
public void execute(FunctionContext functionContext) { public void execute(FunctionContext functionContext) {
Object[] args = this.functionArgumentResolver.resolveFunctionArguments(functionContext);
Object[] args = (functionContext.getArguments().getClass().isArray()) ? (Object[]) functionContext
.getArguments() : new Object[] { functionContext.getArguments() }; Object result = null;
Serializable result = null;
if (functionContext instanceof RegionFunctionContext) {
RegionFunctionContext regionFunctionContext = (RegionFunctionContext) functionContext;
Region<?, ?> region = getRegionForContext(regionFunctionContext);
//TODO: Not sure if filter is needed at this point
Set<?> filter = regionFunctionContext.getFilter();
//Insert the region into the associated position
if (this.regionParameterPosition != null) {
ArrayUtils.insert(args, regionParameterPosition, region);
}
} else {
}
result = invokeTargetMethod(args); result = invokeTargetMethod(args);
@@ -129,7 +112,7 @@ public class PojoFunctionWrapper implements Function {
} }
protected final Serializable invokeTargetMethod(Object[] args) { protected final Object invokeTargetMethod(Object[] args) {
if (logger.isDebugEnabled()) { if (logger.isDebugEnabled()) {
logger.debug(String.format("about to invoke method %s on class %s as function %s", method.getName(), target logger.debug(String.format("about to invoke method %s on class %s as function %s", method.getName(), target
@@ -141,54 +124,36 @@ public class PojoFunctionWrapper implements Function {
} }
return (Serializable) ReflectionUtils.invokeMethod(method, target, (Object[]) args); return (Object) ReflectionUtils.invokeMethod(method, target, (Object[]) args);
}
/*
* @param regionFunctionContext
* @return
*/
private Region<?, ?> getRegionForContext(RegionFunctionContext regionFunctionContext) {
Region<?, ?> region = regionFunctionContext.getDataSet();
if (PartitionRegionHelper.isPartitionedRegion(region)) {
if (logger.isDebugEnabled()) {
logger.debug("this is a partitioned region - filtering local data for context");
}
region = PartitionRegionHelper.getLocalDataForContext(regionFunctionContext);
}
if (logger.isDebugEnabled()) {
logger.debug("region contains " + region.size() + " items");
}
return region;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private void sendResults(ResultSender<Object> resultSender, Serializable result) { private void sendResults(ResultSender<Object> resultSender, Object result) {
if (result == null) { if (result == null) {
resultSender.lastResult(null); resultSender.lastResult(null);
return; return;
} }
Serializable lastItem = result; List<Object> results = null;
List<Serializable> results = null;
if (ObjectUtils.isArray(result)) { if (ObjectUtils.isArray(result)) {
results = Arrays.asList((Serializable[]) result); results = Arrays.asList((Object[]) result);
} else if (List.class.isAssignableFrom(result.getClass())) { } else if (List.class.isAssignableFrom(result.getClass())) {
results = (List<Serializable>) result; results = (List<Object>) result;
} }
if (results != null) { if (results != null) {
int i = 0; int i = 0;
for (Serializable item : results) { for (Object item : results) {
if (i++ < results.size() - 1) { if (i++ < results.size() - 1) {
resultSender.sendResult(item); resultSender.sendResult(item);
} else { } else {
lastItem = item; resultSender.lastResult(item);
} }
} }
} else {
resultSender.lastResult(result);
} }
resultSender.lastResult(lastItem);
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2011 the original author or authors. * Copyright 2002-2012 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 * 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 * the License. You may obtain a copy of the License at

View File

@@ -1,60 +0,0 @@
/*
* Copyright 2002-2011 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.function;
import java.io.Serializable;
import com.gemstone.gemfire.cache.RegionService;
import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.Function;
import com.gemstone.gemfire.cache.execute.FunctionService;
/**
* @author David Turanski
*
*/
public class ServerFunctionExecution<T> extends FunctionExecution<T> {
private final RegionService regionService;
/**
*
* @param regionService e.g., Cache,Client, or GemFireCache
* @param function
* @param args
*/
public ServerFunctionExecution(RegionService regionService, Function function, Serializable... args) {
super(function, args);
this.regionService = regionService;
}
/**
*
* @param regionService e.g., Cache,Client, or GemFireCache
* @param functionId
* @param args
*/
public ServerFunctionExecution(RegionService regionService, String functionId, Serializable... args) {
super(functionId, args);
this.regionService = regionService;
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.FunctionExecution#getExecution()
*/
@Override
protected Execution getExecution() {
return FunctionService.onServer(this.regionService);
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright 2002-2012 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.function.config;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.util.Assert;
/**
* Base class for function execution bean definition builders
* @author David Turanski
*
*/
abstract class AbstractFunctionExecutionBeanDefinitionBuilder {
protected final Log log = LogFactory.getLog(this.getClass());
protected final FunctionExecutionConfiguration configuration;
/**
*
* @param configuration the configuration values
*/
AbstractFunctionExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) {
Assert.notNull(configuration);
this.configuration = configuration;
}
/**
* Build the bean definition
* @param registry
* @return
*/
BeanDefinition build(BeanDefinitionRegistry registry) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(getFunctionProxyFactoryBeanClass());
builder.addConstructorArgValue(configuration.getFunctionExecutionInterface());
BeanDefinitionBuilder functionTemplateBuilder = getGemfireOperationsBeanDefinitionBuilder(registry);
functionTemplateBuilder.setLazyInit(true);
AbstractBeanDefinition functionTemplate = functionTemplateBuilder
.getBeanDefinition();
String functionTemplateName = BeanDefinitionReaderUtils.registerWithGeneratedName(functionTemplate, registry);
builder.addConstructorArgReference(functionTemplateName);
// builder.addConstructorArgValue(functionTemplate);
return builder.getBeanDefinition();
}
/*
* Subclasses implement to specify the types to uses.
*/
protected abstract Class<?> getFunctionProxyFactoryBeanClass();
protected abstract BeanDefinitionBuilder getGemfireOperationsBeanDefinitionBuilder(BeanDefinitionRegistry registry);
}

View File

@@ -0,0 +1,204 @@
/*
* Copyright 2002-2012 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.function.config;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* Annotation based configuration source for function executions
*
* @author David Turanski
*
*/
class AnnotationFunctionExecutionConfigurationSource implements FunctionExecutionConfigurationSource {
private static Log logger = LogFactory.getLog(AnnotationFunctionExecutionConfigurationSource.class);
private static final String BASE_PACKAGES = "basePackages";
private static final String BASE_PACKAGE_CLASSES = "basePackageClasses";
private final AnnotationMetadata metadata;
private final AnnotationAttributes attributes;
private static Set<Class<? extends Annotation>> functionExecutionAnnotationTypes;
static {
functionExecutionAnnotationTypes = new HashSet<Class<? extends Annotation>>();
functionExecutionAnnotationTypes.add(OnRegion.class);
functionExecutionAnnotationTypes.add(OnServer.class);
functionExecutionAnnotationTypes.add(OnServers.class);
functionExecutionAnnotationTypes.add(OnMember.class);
functionExecutionAnnotationTypes.add(OnMembers.class);
}
/**
* Creates a new {@link AnnotationFunctionExecutionConfigurationSource} from the given {@link AnnotationMetadata} and
* annotation.
*
* @param metadata must not be {@literal null}.
*/
AnnotationFunctionExecutionConfigurationSource(AnnotationMetadata metadata) {
Assert.notNull(metadata);
this.attributes = new AnnotationAttributes(metadata.getAnnotationAttributes(EnableGemfireFunctionExecutions.class.getName()));
this.metadata = metadata;
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.FunctionExecutionConfigurationSource#getSource()
*/
@Override
public Object getSource() {
// TODO Auto-generated method stub
return this.metadata;
}
static Set<Class<? extends Annotation>> getFunctionExecutionAnnotationTypes() {
return functionExecutionAnnotationTypes;
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.FunctionExecutionConfigurationSource#getBasePackages()
*/
@Override
public Iterable<String> getBasePackages() {
String[] value = attributes.getStringArray("value");
String[] basePackages = attributes.getStringArray(BASE_PACKAGES);
Class<?>[] basePackageClasses = attributes.getClassArray(BASE_PACKAGE_CLASSES);
// Default configuration - return package of annotated class
if (value.length == 0 && basePackages.length == 0 && basePackageClasses.length == 0) {
String className = metadata.getClassName();
return Collections.singleton(className.substring(0, className.lastIndexOf('.')));
}
Set<String> packages = new HashSet<String>();
packages.addAll(Arrays.asList(value));
packages.addAll(Arrays.asList(basePackages));
for (Class<?> typeName : basePackageClasses) {
packages.add(ClassUtils.getPackageName(typeName));
}
return packages;
}
@Override
public Collection<ScannedGenericBeanDefinition> getCandidates(ResourceLoader loader) {
ClassPathScanningCandidateComponentProvider scanner = new FunctionExecutionComponentProvider(getIncludeFilters(),functionExecutionAnnotationTypes);
scanner.setResourceLoader(loader);
for (TypeFilter filter : getExcludeFilters()) {
scanner.addExcludeFilter(filter);
}
Set<ScannedGenericBeanDefinition> result = new HashSet<ScannedGenericBeanDefinition>();
for (String basePackage : getBasePackages()) {
logger.debug("scanning package " + basePackage);
Collection<BeanDefinition> components = scanner.findCandidateComponents(basePackage);
for (BeanDefinition definition : components) {
result.add((ScannedGenericBeanDefinition)definition);
}
}
return result;
}
protected Iterable<TypeFilter> getIncludeFilters() {
return parseFilters("includeFilters");
}
protected Iterable<TypeFilter> getExcludeFilters() {
return parseFilters("excludeFilters");
}
private Set<TypeFilter> parseFilters(String attributeName) {
Set<TypeFilter> result = new HashSet<TypeFilter>();
AnnotationAttributes[] filters = attributes.getAnnotationArray(attributeName);
for (AnnotationAttributes filter : filters) {
result.addAll(typeFiltersFor(filter));
}
return result;
}
/**
* Copy of {@code ComponentScanAnnotationParser#typeFiltersFor}.
*
* @param filterAttributes
* @return
*/
private List<TypeFilter> typeFiltersFor(AnnotationAttributes filterAttributes) {
List<TypeFilter> typeFilters = new ArrayList<TypeFilter>();
FilterType filterType = filterAttributes.getEnum("type");
for (Class<?> filterClass : filterAttributes.getClassArray("value")) {
switch (filterType) {
case ANNOTATION:
Assert.isAssignable(Annotation.class, filterClass, "An error occured when processing a @ComponentScan "
+ "ANNOTATION type filter: ");
@SuppressWarnings("unchecked")
Class<Annotation> annoClass = (Class<Annotation>) filterClass;
typeFilters.add(new AnnotationTypeFilter(annoClass));
break;
case ASSIGNABLE_TYPE:
typeFilters.add(new AssignableTypeFilter(filterClass));
break;
case CUSTOM:
Assert.isAssignable(TypeFilter.class, filterClass, "An error occured when processing a @ComponentScan "
+ "CUSTOM type filter: ");
typeFilters.add(BeanUtils.instantiateClass(filterClass, TypeFilter.class));
break;
default:
throw new IllegalArgumentException("unknown filter type " + filterType);
}
}
return typeFilters;
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2002-2012 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.function.config;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Import;
/**
* Enables classpath scanning for interfaces annotated as GemFire function executions (function invocations).
* These include interfaces annotated with one of {code} @OnRegion, @OnServer, @OnServers, @OnMember, @OnMembers{code}
*
* @author David Turanski
*
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(FunctionExecutionBeanDefinitionRegistrar.class)
public @interface EnableGemfireFunctionExecutions {
/**
* Alias for the {@link #basePackages()} attribute. Allows for more concise annotation declarations e.g.:
* {@code @EnableGemfireRepositories("org.my.pkg")} instead of
* {@code @EnableGemfireRepositories(basePackages="org.my.pkg")}.
*/
String[] value() default {};
/**
* Base packages to scan for annotated components. {@link #value()} is an alias for (and mutually exclusive with) this
* attribute. Use {@link #basePackageClasses()} for a type-safe alternative to String-based package names.
*/
String[] basePackages() default {};
/**
* Type-safe alternative to {@link #basePackages()} for specifying the packages to scan for annotated components. The
* package of each class specified will be scanned. Consider creating a special no-op marker class or interface in
* each package that serves no purpose other than being referenced by this attribute.
*/
Class<?>[] basePackageClasses() default {};
/**
* Specifies which types are eligible for component scanning. Further narrows the set of candidate components from
* everything in {@link #basePackages()} to everything in the base packages that matches the given filter or filters.
*/
Filter[] includeFilters() default {};
/**
* Specifies which types are not eligible for component scanning.
*/
Filter[] excludeFilters() default {};
}

View File

@@ -19,9 +19,14 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy; import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
import org.springframework.context.annotation.ComponentScan.Filter; import org.springframework.context.annotation.Import;
/** /**
*
* Enables Gemfire annotated function implementations. Causes the container to
* discover any beans that are annotated with {code} @GemfireFunction {code}, wrap them in
* a {@link PojoFunctionWrapper}, and register them with the cache.
*
* @author David Turanski * @author David Turanski
* *
*/ */
@@ -29,36 +34,6 @@ import org.springframework.context.annotation.ComponentScan.Filter;
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Documented @Documented
@Inherited @Inherited
@Import(GemfireFunctionPostBeanProcessorRegistrar.class)
public @interface EnableGemfireFunctions { public @interface EnableGemfireFunctions {
/**
* Alias for the {@link #basePackages()} attribute. Allows for more concise annotation declarations e.g.:
* {@code @EnableGemfireRepositories("org.my.pkg")} instead of
* {@code @EnableGemfireRepositories(basePackages="org.my.pkg")}.
*/
String[] value() default {};
/**
* Base packages to scan for annotated components. {@link #value()} is an alias for (and mutually exclusive with) this
* attribute. Use {@link #basePackageClasses()} for a type-safe alternative to String-based package names.
*/
String[] basePackages() default {};
/**
* Type-safe alternative to {@link #basePackages()} for specifying the packages to scan for annotated components. The
* package of each class specified will be scanned. Consider creating a special no-op marker class or interface in
* each package that serves no purpose other than being referenced by this attribute.
*/
Class<?>[] basePackageClasses() default {};
/**
* Specifies which types are eligible for component scanning. Further narrows the set of candidate components from
* everything in {@link #basePackages()} to everything in the base packages that matches the given filter or filters.
*/
Filter[] includeFilters() default {};
/**
* Specifies which types are not eligible for component scanning.
*/
Filter[] excludeFilters() default {};
} }

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2002-2012 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.function.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
* Used to inject a set of cache keys into a function execution, The annotated parameter must be of type
* {@link Set}. This is used by the function invocation to specify a set of keys of interest and also to define
* an additional parameter on the function implementation method containing the filter.
* @author David Turanski
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER})
public @interface Filter {
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2002-2012 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.function.config;
/**
*
* Maps the annotation type to the corresponding function execution bean definition builder
* @author David Turanski
*
*/
abstract class FunctionExecutionBeanDefinitionBuilderFactory {
static AbstractFunctionExecutionBeanDefinitionBuilder newInstance(FunctionExecutionConfiguration configuration) {
String functionExectionAnnotation = configuration.getAnnotationType();
if (functionExectionAnnotation.equals(OnRegion.class.getName())) {
return new OnRegionExecutionBeanDefinitionBuilder(configuration);
}
if (functionExectionAnnotation.equals(OnServer.class.getName())) {
return new OnServerExecutionBeanDefinitionBuilder(configuration);
}
if (functionExectionAnnotation.equals(OnServers.class.getName())) {
return new OnServersExecutionBeanDefinitionBuilder(configuration);
}
if (functionExectionAnnotation.equals(OnMember.class.getName())) {
return new OnMemberExecutionBeanDefinitionBuilder(configuration);
}
if (functionExectionAnnotation.equals(OnMembers.class.getName())) {
return new OnMembersExecutionBeanDefinitionBuilder(configuration);
}
return null;
}
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright 2002-2012 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.function.config;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* {@link ImportBeanDefinitionRegistrar} for {code} @EnableGemfireFunctionExecutions {code}
* Scans for interfaces annotated with one of {code} @OnRegion, @OnServer, @OnServers, @OnMember, @OnMembers {code}
* @author David Turanski
*
*/
public class FunctionExecutionBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
private static Log logger = LogFactory.getLog(FunctionExecutionBeanDefinitionRegistrar.class);
/* (non-Javadoc)
* @see org.springframework.context.annotation.ImportBeanDefinitionRegistrar#registerBeanDefinitions(org.springframework.core.type.AnnotationMetadata, org.springframework.beans.factory.support.BeanDefinitionRegistry)
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {
logger.debug("registering bean definitions...");
ResourceLoader resourceLoader = new DefaultResourceLoader();
AnnotationFunctionExecutionConfigurationSource configurationSource = new AnnotationFunctionExecutionConfigurationSource(
annotationMetadata);
Set<String> functionExecutionAnnotationTypes = new HashSet<String>(
AnnotationFunctionExecutionConfigurationSource.getFunctionExecutionAnnotationTypes().size());
for (Class<?> annotation : AnnotationFunctionExecutionConfigurationSource.getFunctionExecutionAnnotationTypes()) {
functionExecutionAnnotationTypes.add(annotation.getName());
}
for (ScannedGenericBeanDefinition beanDefinition : configurationSource.getCandidates(resourceLoader)) {
String functionExecutionAnnotation = getFunctionExecutionAnnotation(beanDefinition,
functionExecutionAnnotationTypes);
Assert.notNull(functionExecutionAnnotation);
String beanName = (String) beanDefinition.getMetadata()
.getAnnotationAttributes(functionExecutionAnnotation).get("id");
if (!StringUtils.hasLength(beanName)) {
beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, registry);
}
AbstractFunctionExecutionBeanDefinitionBuilder builder = FunctionExecutionBeanDefinitionBuilderFactory
.newInstance(new FunctionExecutionConfiguration(beanDefinition, functionExecutionAnnotation));
registry.registerBeanDefinition(beanName, builder.build(registry));
}
}
private String getFunctionExecutionAnnotation(ScannedGenericBeanDefinition beanDefinition,
Set<String> functionExecutionAnnotationTypes) {
Set<String> annotationTypes = beanDefinition.getMetadata().getAnnotationTypes();
String functionExecutionAnnotation = null;
for (String annotation : annotationTypes) {
if (functionExecutionAnnotationTypes.contains(annotation)) {
Assert.isNull(functionExecutionAnnotation, String.format(
"interface %s contains multiple function execution annotations: %s, %s",
beanDefinition.getBeanClassName(), functionExecutionAnnotation, annotation));
functionExecutionAnnotation = annotation;
}
}
return functionExecutionAnnotation;
}
}

View File

@@ -0,0 +1,218 @@
/*
* Copyright 2002-2012 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.function.config;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.annotation.Inherited;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.AnnotatedBeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.classreading.MetadataReader;
import org.springframework.core.type.classreading.MetadataReaderFactory;
import org.springframework.core.type.filter.AbstractTypeHierarchyTraversingFilter;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.data.gemfire.function.execution.FunctionExecution;
import org.springframework.util.Assert;
/**
* Custom {@link ClassPathScanningCandidateComponentProvider} scanning for interfaces annotated for
* function execution
*
* @author David Turanski
*/
class FunctionExecutionComponentProvider extends ClassPathScanningCandidateComponentProvider {
private final Set<Class<? extends Annotation>> functionExecutionAnnotationTypes;
/**
* Creates a new {@link FunctionExecutionComponentProvider} using the given {@link TypeFilter} to include components to be
* picked up.
*
* @param includeFilters the {@link TypeFilter}s to select function execution interfaces to consider, must not be
* {@literal null}.
*/
public FunctionExecutionComponentProvider(Iterable<? extends TypeFilter> includeFilters , Set<Class<? extends Annotation>> functionExecutionAnnotationTypes) {
super(false);
this.functionExecutionAnnotationTypes = functionExecutionAnnotationTypes;
Assert.notNull(includeFilters);
if (includeFilters.iterator().hasNext()) {
for (TypeFilter filter : includeFilters) {
addIncludeFilter(filter);
}
} else {
for (Class<? extends Annotation> annotation: this.functionExecutionAnnotationTypes) {
super.addIncludeFilter(new AnnotationTypeFilter(annotation, true, true));
}
}
}
/**
* Custom extension of {@link #addIncludeFilter(TypeFilter)} to extend the added {@link TypeFilter}. For the
* {@link TypeFilter} handed we'll have two filters registered: one additionally enforcing the
* {@link FunctionExecutionDefinition} annotation, the other one forcing the extension of {@link FunctionExecution}.
*
* @see ClassPathScanningCandidateComponentProvider#addIncludeFilter(TypeFilter)
*/
@Override
public void addIncludeFilter(TypeFilter includeFilter) {
List<TypeFilter> filterPlusInterface = new ArrayList<TypeFilter>();
filterPlusInterface.add(includeFilter);
super.addIncludeFilter(new AllTypeFilter(filterPlusInterface));
List<TypeFilter> filterPlusAnnotation = new ArrayList<TypeFilter>();
filterPlusAnnotation.add(includeFilter);
for (Class<? extends Annotation> annotation: this.functionExecutionAnnotationTypes) {
filterPlusAnnotation.add(new AnnotationTypeFilter(annotation, true, true));
}
super.addIncludeFilter(new AllTypeFilter(filterPlusAnnotation));
}
/*
* (non-Javadoc)
* @see org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider#isCandidateComponent(org.springframework.beans.factory.annotation.AnnotatedBeanDefinition)
*/
@Override
protected boolean isCandidateComponent(AnnotatedBeanDefinition beanDefinition) {
boolean isTopLevelType = !beanDefinition.getMetadata().hasEnclosingClass();
return isTopLevelType;
}
// Copy of Spring's AnnotationTypeFilter until SPR-8336 gets resolved.
/**
* A simple filter which matches classes with a given annotation, checking inherited annotations as well.
* <p>
* The matching logic mirrors that of <code>Class.isAnnotationPresent()</code>.
*
* @author Mark Fisher
* @author Ramnivas Laddad
* @author Juergen Hoeller
* @since 2.5
*/
private static class AnnotationTypeFilter extends AbstractTypeHierarchyTraversingFilter {
private final Class<? extends Annotation> annotationType;
private final boolean considerMetaAnnotations;
/**
* Create a new AnnotationTypeFilter for the given annotation type. This filter will also match meta-annotations. To
* disable the meta-annotation matching, use the constructor that accepts a ' <code>considerMetaAnnotations</code>'
* argument. The filter will not match interfaces.
*
* @param annotationType the annotation type to match
*/
@SuppressWarnings("unused")
public AnnotationTypeFilter(Class<? extends Annotation> annotationType) {
this(annotationType, true);
}
/**
* Create a new AnnotationTypeFilter for the given annotation type. The filter will not match interfaces.
*
* @param annotationType the annotation type to match
* @param considerMetaAnnotations whether to also match on meta-annotations
*/
public AnnotationTypeFilter(Class<? extends Annotation> annotationType, boolean considerMetaAnnotations) {
this(annotationType, considerMetaAnnotations, false);
}
/**
* Create a new {@link AnnotationTypeFilter} for the given annotation type.
*
* @param annotationType the annotation type to match
* @param considerMetaAnnotations whether to also match on meta-annotations
* @param considerInterfaces whether to also match interfaces
*/
public AnnotationTypeFilter(Class<? extends Annotation> annotationType, boolean considerMetaAnnotations,
boolean considerInterfaces) {
super(annotationType.isAnnotationPresent(Inherited.class), considerInterfaces);
this.annotationType = annotationType;
this.considerMetaAnnotations = considerMetaAnnotations;
}
@Override
protected boolean matchSelf(MetadataReader metadataReader) {
AnnotationMetadata metadata = metadataReader.getAnnotationMetadata();
return metadata.hasAnnotation(this.annotationType.getName())
|| (this.considerMetaAnnotations && metadata.hasMetaAnnotation(this.annotationType.getName()));
}
@Override
protected Boolean matchSuperClass(String superClassName) {
if (Object.class.getName().equals(superClassName)) {
return Boolean.FALSE;
} else if (superClassName.startsWith("java.")) {
try {
Class<?> clazz = getClass().getClassLoader().loadClass(superClassName);
return (clazz.getAnnotation(this.annotationType) != null);
} catch (ClassNotFoundException ex) {
// Class not found - can't determine a match that way.
}
}
return null;
}
}
/**
* Helper class to create a {@link TypeFilter} that matches if all the delegates match.
*
* @author Oliver Gierke
*/
private static class AllTypeFilter implements TypeFilter {
private final List<TypeFilter> delegates;
/**
* Creates a new {@link AllTypeFilter} to match if all the given delegates match.
*
* @param delegates must not be {@literal null}.
*/
public AllTypeFilter(List<TypeFilter> delegates) {
Assert.notNull(delegates);
this.delegates = delegates;
}
/*
* (non-Javadoc)
* @see org.springframework.core.type.filter.TypeFilter#match(org.springframework.core.type.classreading.MetadataReader, org.springframework.core.type.classreading.MetadataReaderFactory)
*/
public boolean match(MetadataReader metadataReader, MetadataReaderFactory metadataReaderFactory) throws IOException {
for (TypeFilter filter : delegates) {
if (!filter.match(metadataReader, metadataReaderFactory)) {
return false;
}
}
return true;
}
}
}

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2002-2012 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.function.config;
import java.util.Map;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.util.Assert;
/**
* Function execution configuration used by bean definition builders
*
* @author David Turanski
*
*/
class FunctionExecutionConfiguration {
private final Map<String,Object> attributes;
private Class<?> functionExecutionInterface;
private final String annotationType;
FunctionExecutionConfiguration(ScannedGenericBeanDefinition beanDefinition, String annotationType) {
this.attributes = beanDefinition.getMetadata().getAnnotationAttributes(annotationType,true);
try {
this.functionExecutionInterface = beanDefinition.resolveBeanClass(beanDefinition.getClass().getClassLoader());
Assert.isTrue(functionExecutionInterface.isInterface(),
String.format("The annotation %s only applies to an interface. It is not valid for the type %s",
annotationType, functionExecutionInterface.getName()));
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
this.annotationType = annotationType;
}
Class<?> getFunctionExecutionInterface() {
return this.functionExecutionInterface;
}
Map<String, Object> getAttributes() {
return this.attributes;
}
Object getAttribute(String name) {
return attributes.get(name);
}
String getAnnotationType() {
return this.annotationType;
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2002-2012 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.function.config;
import java.util.Collection;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.io.ResourceLoader;
/**
* Interface for function execution configuration sources (e.g., annotation or XML configuration) to configure
* classpath scanning of annotated interfaces to implement proxies that invoke Gemfire functions
*
* @author David Turanski
*
*/
interface FunctionExecutionConfigurationSource {
/**
* Returns the actual source object that the configuration originated from. Will be used by the tooling to give visual
* feedback on where the repository instances actually come from.
*
* @return must not be {@literal null}.
*/
Object getSource();
/**
* Returns the base packages the repository interfaces shall be found under.
*
* @return must not be {@literal null}.
*/
Iterable<String> getBasePackages();
/**
* Returns the scanned bean definitions
*
* @param loader
* @return
*/
Collection<ScannedGenericBeanDefinition> getCandidates(ResourceLoader loader);
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2002-2012 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.function.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to bind an interface method to a GemFire function id
* @author David Turanski
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface FunctionId {
/**
* The name of the registered function
* @return the function id
*/
String value();
}

View File

@@ -18,6 +18,9 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target; import java.lang.annotation.Target;
/** /**
*
* Used to declare a concrete method as a GemFire function implementation
*
* @author David Turanski * @author David Turanski
* *
*/ */

View File

@@ -12,7 +12,6 @@
*/ */
package org.springframework.data.gemfire.function.config; package org.springframework.data.gemfire.function.config;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.Modifier; import java.lang.reflect.Modifier;
import java.util.Map; import java.util.Map;
@@ -24,13 +23,16 @@ import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils; import org.springframework.util.ReflectionUtils;
/** /**
* A {@link BeanPostProcessor} to discover components wired as function implementations. That is
* beans that contain methods annotated with {code} @GemfireFunction {code}
*
* @author David Turanski * @author David Turanski
* *
*/ */
public class GemfireFunctionBeanPostProcessor implements BeanPostProcessor { public class GemfireFunctionBeanPostProcessor implements BeanPostProcessor {
private static final String GEMFIRE_FUNCTION_ANNOTATION_NAME = GemfireFunction.class.getName(); private static final String GEMFIRE_FUNCTION_ANNOTATION_NAME = GemfireFunction.class.getName();
private static final String REGION_DATA_ANNOTATION_NAME = RegionData.class.getName();
/* (non-Javadoc) /* (non-Javadoc)
* @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String) * @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String)
@@ -45,7 +47,14 @@ public class GemfireFunctionBeanPostProcessor implements BeanPostProcessor {
*/ */
@Override @Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException { public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
registerAnyDeclaredGemfireFunctionMethods(bean);
return bean;
}
private void registerAnyDeclaredGemfireFunctionMethods (Object bean) {
Method[] methods = ReflectionUtils.getAllDeclaredMethods(bean.getClass()); Method[] methods = ReflectionUtils.getAllDeclaredMethods(bean.getClass());
for (Method method: methods) { for (Method method: methods) {
@@ -53,34 +62,9 @@ public class GemfireFunctionBeanPostProcessor implements BeanPostProcessor {
if (annotation != null) { if (annotation != null) {
Assert.isTrue(Modifier.isPublic(method.getModifiers()),"The method " + method.getName()+ " annotated with" + GEMFIRE_FUNCTION_ANNOTATION_NAME+ " must be public"); Assert.isTrue(Modifier.isPublic(method.getModifiers()),"The method " + method.getName()+ " annotated with" + GEMFIRE_FUNCTION_ANNOTATION_NAME+ " must be public");
Map<String,Object> attributes = AnnotationUtils.getAnnotationAttributes(annotation,false,true); Map<String,Object> attributes = AnnotationUtils.getAnnotationAttributes(annotation,false,true);
processParameterAnnotations(method);
GemfireFunctionUtils.registerFunctionForPojoMethod(bean, method, attributes, false); GemfireFunctionUtils.registerFunctionForPojoMethod(bean, method, attributes, false);
}
}
return bean;
}
private void processParameterAnnotations(Method method) {
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
if (parameterAnnotations.length == 0) {
return;
}
Class<?>[] paramTypes = method.getParameterTypes();
for (int i=0; i< parameterAnnotations.length; i++) {
Annotation[] annotations = parameterAnnotations[i];
if (annotations.length > 0) {
System.out.println("found annotations for parameter in position " + i + " " + paramTypes[i] );
for (Annotation annotation:annotations) {
System.out.println("Annotation type:" + annotation.annotationType().getName());
}
} }
} }
} }
} }

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2002-2012 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.function.config;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
/**
* and {@link ImportBeanDefinitionRegistrar} to register the {@link GemfireFunctionBeanPostProcessor}
*
* @author David Turanski
*
*/
public class GemfireFunctionPostBeanProcessorRegistrar implements ImportBeanDefinitionRegistrar {
/* (non-Javadoc)
* @see org.springframework.context.annotation.ImportBeanDefinitionRegistrar#registerBeanDefinitions(org.springframework.core.type.AnnotationMetadata, org.springframework.beans.factory.support.BeanDefinitionRegistry)
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// TODO Auto-generated method stub
}
}

View File

@@ -12,35 +12,49 @@
*/ */
package org.springframework.data.gemfire.function.config; package org.springframework.data.gemfire.function.config;
import java.lang.annotation.Annotation;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.util.Arrays;
import java.util.List;
import java.util.Map; import java.util.Map;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
import org.springframework.data.gemfire.function.PojoFunctionWrapper; import org.springframework.data.gemfire.function.PojoFunctionWrapper;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.execute.FunctionService; import com.gemstone.gemfire.cache.execute.FunctionService;
/** /**
*
* @author David Turanski * @author David Turanski
* *
*/ */
public abstract class GemfireFunctionUtils { public abstract class GemfireFunctionUtils {
private static Log log = LogFactory.getLog(GemfireFunctionUtils.class); private static Log log = LogFactory.getLog(GemfireFunctionUtils.class);
public static void registerFunctionForPojoMethod(Object target, Method method, Map<String,Object> attributes, boolean overwrite) { /**
String id = attributes.containsKey("id") ? (String)attributes.get("id") : ""; * Wrap a target object and method in a GemFire Function and register the function to the {@link FunctionService}
*
PojoFunctionWrapper function = new PojoFunctionWrapper(target,method, id); * @param target the target object
* @param method the method bound to the function
* @param attributes function attributes
* @param overwrite if true, will replace the existing function
*/
public static void registerFunctionForPojoMethod(Object target, Method method, Map<String, Object> attributes,
boolean overwrite) {
String id = attributes.containsKey("id") ? (String) attributes.get("id") : "";
PojoFunctionWrapper function = new PojoFunctionWrapper(target, method, id);
if (attributes.containsKey("HA")) { if (attributes.containsKey("HA")) {
function.setHA((Boolean)attributes.get("HA")); function.setHA((Boolean) attributes.get("HA"));
} }
if (attributes.containsKey("optimizeForWrite")) { if (attributes.containsKey("optimizeForWrite")) {
function.setOptimizeForWrite((Boolean)attributes.get("optimizeForWrite")); function.setOptimizeForWrite((Boolean) attributes.get("optimizeForWrite"));
} }
if (FunctionService.isRegistered(function.getId())) { if (FunctionService.isRegistered(function.getId())) {
if (overwrite) { if (overwrite) {
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
@@ -49,7 +63,7 @@ public abstract class GemfireFunctionUtils {
FunctionService.unregisterFunction(function.getId()); FunctionService.unregisterFunction(function.getId());
} }
} }
if (!FunctionService.isRegistered(function.getId())){ if (!FunctionService.isRegistered(function.getId())) {
FunctionService.registerFunction(function); FunctionService.registerFunction(function);
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {
log.debug("registered function " + function.getId()); log.debug("registered function " + function.getId());
@@ -60,4 +74,42 @@ public abstract class GemfireFunctionUtils {
} }
} }
} }
/**
* Determine the order position of a an annotated method parameter
*
* @param method the {@link Method} instance
* @param targetAnnotationType the annotation
* @param requiredTypes an array of valid parameter types for the annotation
* @return the parameter position or -1 if the annotated parameter is not found
*/
public static int getAnnotationParameterPosition(Method method, Class<?> targetAnnotationType, Class<?>[] requiredTypes) {
Annotation[][] parameterAnnotations = method.getParameterAnnotations();
if (parameterAnnotations.length > 0) {
int position = -1;
Class<?>[] paramTypes = method.getParameterTypes();
List<Class<?>> requiredTypesList = Arrays.asList(requiredTypes);
for (int i = 0; i < parameterAnnotations.length; i++) {
Annotation[] annotations = parameterAnnotations[i];
if (annotations.length > 0) {
for (Annotation annotation : annotations) {
if (annotation.annotationType().equals(targetAnnotationType)) {
Assert.state(position < 0, String.format("Method %s signature cannot contain more than one parameter annotated with type %s"
,method.getName(),targetAnnotationType.getName()));
Assert.isTrue(requiredTypesList.contains(paramTypes[i]), String.format(
"Parameter annotated with %s must be one of type %s in method %s", targetAnnotationType.getName(),
StringUtils.arrayToCommaDelimitedString(requiredTypes), method.getName()));
position = i;
}
}
}
}
return position;
}
return -1;
}
} }

View File

@@ -0,0 +1,65 @@
/*
* Copyright 2002-2012 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.function.config;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.data.gemfire.function.execution.GemfireFunctionProxyFactoryBean;
import org.springframework.util.StringUtils;
/**
* A base class for OnMember and OnMembers function execution bean definition builders.
*
* @author David Turanski
*
*/
abstract class MemberBasedExecutionBeanDefinitionBuilder extends AbstractFunctionExecutionBeanDefinitionBuilder {
/**
* @param configuration
*/
public MemberBasedExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) {
super(configuration);
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.AbstractFunctionExecutionBeanDefinitionBuilder#getGemfireOperationsBeanDefinitionBuilder(org.springframework.beans.factory.support.BeanDefinitionRegistry)
*/
@Override
protected BeanDefinitionBuilder getGemfireOperationsBeanDefinitionBuilder(BeanDefinitionRegistry registry) {
BeanDefinitionBuilder functionTemplateBuilder = BeanDefinitionBuilder.genericBeanDefinition(getGemfireOperationsClass());
String groups = (String)configuration.getAttribute("groups");
if (StringUtils.hasText(groups)) {
functionTemplateBuilder.addConstructorArgValue(StringUtils.commaDelimitedListToStringArray(groups));
}
return functionTemplateBuilder;
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.AbstractFunctionExecutionBeanDefinitionBuilder#getFunctionProxyFactoryBeanClass()
*/
@Override
protected Class<?> getFunctionProxyFactoryBeanClass() {
return GemfireFunctionProxyFactoryBean.class;
}
protected abstract Class<?> getGemfireOperationsClass();
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2002-2012 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.function.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to declare an interface as a GemFire OnMember Function Execution
*
* @author David Turanski
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface OnMember {
/**
* The bean name and also the default name of the registered function, if single method on the interface.
* If multiple methods declared use the (@link FunctionId) annotation on each method
* @return the function id
*/
String id() default "";
//TODO SpEL expression for DistributedMember?
/**
* groups
*/
String groups() default "";
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2002-2012 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.function.config;
import org.springframework.data.gemfire.function.execution.GemfireOnMemberFunctionTemplate;
/**
*
* @author David Turanski
*
*/
class OnMemberExecutionBeanDefinitionBuilder extends MemberBasedExecutionBeanDefinitionBuilder {
/**
* @param configuration
*/
OnMemberExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) {
super(configuration);
// TODO Auto-generated constructor stub
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.MemberBasedExecutionBeanDefinitionBuilder#getGemfireOperationsClass()
*/
@Override
protected Class<?> getGemfireOperationsClass() {
return GemfireOnMemberFunctionTemplate.class;
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2002-2012 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.function.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to declare an interface as a GemFire OnMembers Function Execution
* @author David Turanski
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface OnMembers {
/**
* The bean name and also the default name of the registered function, if single method on the interface.
* If multiple methods declared use the (@link FunctionId) annotation on each method
* @return the function id
*/
String id() default "";
//TODO SpEL expression for DistributedMembers?
/**
* groups
*/
String groups() default "";
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2002-2012 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.function.config;
import org.springframework.data.gemfire.function.execution.GemfireOnMembersFunctionTemplate;
/**
* @author David Turanski
*
*/
class OnMembersExecutionBeanDefinitionBuilder extends MemberBasedExecutionBeanDefinitionBuilder {
/**
* @param configuration
*/
OnMembersExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) {
super(configuration);
// TODO Auto-generated constructor stub
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.MemberBasedExecutionBeanDefinitionBuilder#getGemfireOperationsClass()
*/
@Override
protected Class<?> getGemfireOperationsClass() {
return GemfireOnMembersFunctionTemplate.class;
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2002-2012 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.function.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to declare an interface as a GemFire OnRegion Function Execution
* @author David Turanski
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface OnRegion {
/**
* The bean name and also the default name of the registered function, if single method on the interface.
* If multiple methods declared use the (@link FunctionId) annotation on each method
* @return the function id
*/
String id() default "";
/**
* The reference to the bean id of the region
* @return the region id
*/
String region();
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2002-2012 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.function.config;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.data.gemfire.function.execution.GemfireOnRegionFunctionTemplate;
import org.springframework.data.gemfire.function.execution.OnRegionFunctionProxyFactoryBean;
/**
* @author David Turanski
*
*/
class OnRegionExecutionBeanDefinitionBuilder extends AbstractFunctionExecutionBeanDefinitionBuilder {
/**
* @param configuration
*/
OnRegionExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) {
super(configuration);
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.AbstractFunctionExecutionBeanDefinitionBuilder#getGemfireOperationsBeanDefinitionBuilder(org.springframework.beans.factory.support.BeanDefinitionRegistry)
*/
@Override
protected BeanDefinitionBuilder getGemfireOperationsBeanDefinitionBuilder(BeanDefinitionRegistry registry) {
BeanDefinitionBuilder functionTemplateBuilder = BeanDefinitionBuilder.genericBeanDefinition(GemfireOnRegionFunctionTemplate.class);
functionTemplateBuilder.addConstructorArgReference((String)configuration.getAttribute("region"));
return functionTemplateBuilder;
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.AbstractFunctionExecutionBeanDefinitionBuilder#getFunctionProxyFactoryBeanClass()
*/
@Override
protected Class<?> getFunctionProxyFactoryBeanClass() {
return OnRegionFunctionProxyFactoryBean.class;
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2002-2012 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.function.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to declare an interface as a GemFire OnServer Function Execution
* @author David Turanski
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface OnServer {
/**
* The bean name and also the default name of the registered function, if single method on the interface.
* If multiple methods declared use the (@link FunctionId) annotation on each method
* @return the function id
*/
String id() default "";
/**
* The pool bean id (optional)
* @return
*/
String pool() default "";
/**
* A reference to the cache
*/
String cache() default "";
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2002-2012 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.function.config;
import org.springframework.data.gemfire.function.execution.GemfireOnServerFunctionTemplate;
/**
* @author David Turanski
*
*/
class OnServerExecutionBeanDefinitionBuilder extends ServerBasedExecutionBeanDefinitionBuilder {
/**
* @param configuration
*/
OnServerExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) {
super(configuration);
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.ServerBasedExecutionBeanDefinitionBuilder#getGemfireOperationsClass()
*/
@Override
protected Class<?> getGemfireOperationsClass() {
return GemfireOnServerFunctionTemplate.class;
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2002-2012 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.function.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to declare an interface as a GemFire OnServers Function Execution
* @author David Turanski
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface OnServers {
/**
* The bean name and also the default name of the registered function, if single method on the interface.
* If multiple methods declared use the (@link FunctionId) annotation on each method
* @return the function id
*/
String id() default "";
/**
* The pool bean name (optional)
* @return
*/
String pool() default "";
/**
* A reference to the cache
*/
String cache() default "gemfireCache";
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2002-2012 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.function.config;
import org.springframework.data.gemfire.function.execution.GemfireOnServersFunctionTemplate;
/**
* @author David Turanski
*
*/
class OnServersExecutionBeanDefinitionBuilder extends ServerBasedExecutionBeanDefinitionBuilder {
/**
* @param configuration
*/
OnServersExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) {
super(configuration);
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.ServerBasedExecutionBeanDefinitionBuilder#getGemfireOperationsClass()
*/
@Override
protected Class<?> getGemfireOperationsClass() {
return GemfireOnServersFunctionTemplate.class;
}
}

View File

@@ -23,11 +23,11 @@ import java.lang.annotation.Target;
* {@link Map}. The contents depends on the region configuration (for a partitioned region, this will * {@link Map}. The contents depends on the region configuration (for a partitioned region, this will
* contain only entries for the local partition) * contain only entries for the local partition)
* and any filters configured for the function context. * and any filters configured for the function context.
*
* @author David Turanski * @author David Turanski
* *
*/ */
@Retention(RetentionPolicy.RUNTIME) @Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER}) @Target({ElementType.PARAMETER})
public @interface RegionData { public @interface RegionData {
String value() default "";
} }

View File

@@ -0,0 +1,75 @@
/*
* Copyright 2002-2012 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.function.config;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.data.gemfire.config.GemfireConstants;
import org.springframework.data.gemfire.function.execution.GemfireFunctionProxyFactoryBean;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* @author David Turanski
*
*/
abstract class ServerBasedExecutionBeanDefinitionBuilder extends AbstractFunctionExecutionBeanDefinitionBuilder {
/**
* @param configuration
*/
ServerBasedExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) {
super(configuration);
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.AbstractFunctionExecutionBeanDefinitionBuilder#getGemfireOperationsBeanDefinitionBuilder(org.springframework.beans.factory.support.BeanDefinitionRegistry)
*/
@Override
protected BeanDefinitionBuilder getGemfireOperationsBeanDefinitionBuilder(BeanDefinitionRegistry registry) {
BeanDefinitionBuilder functionTemplateBuilder = BeanDefinitionBuilder.genericBeanDefinition(getGemfireOperationsClass());
String pool = (String)configuration.getAttribute("pool");
String cache = (String)configuration.getAttribute("cache");
Assert.state(!(StringUtils.hasText(pool) && StringUtils.hasText(cache)),
String.format("invalid configuration for interface %s. Cannot specify both 'pool' and 'cache'",
configuration.getFunctionExecutionInterface().getName()));
if (StringUtils.hasText(pool)) {
functionTemplateBuilder.addConstructorArgReference(pool);
} else {
if (!StringUtils.hasText(cache)) {
cache = GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME;
}
functionTemplateBuilder.addConstructorArgReference(cache);
}
return functionTemplateBuilder;
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.AbstractFunctionExecutionBeanDefinitionBuilder#getFunctionProxyFactoryBeanClass()
*/
@Override
protected Class<?> getFunctionProxyFactoryBeanClass() {
return GemfireFunctionProxyFactoryBean.class;
}
protected abstract Class<?> getGemfireOperationsClass();
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright 2002-2012 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.function.execution;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.Function;
/**
*
* The base class for Gemfire function templates used to invoke Gemfire functions
* @author David Turanski
*
*/
abstract class AbstractFunctionTemplate implements GemfireFunctionOperations {
protected Log log = LogFactory.getLog(this.getClass());
protected long timeout;
@Override
public <T> Iterable<T> execute(Function function, Object... args) {
FunctionExecution functionExecution = getFunctionExecution()
.setArgs(args)
.setFunction(function)
.setTimeout(timeout);
return execute(functionExecution);
}
@Override
public <T> T executeAndExtract(Function function, Object... args) {
FunctionExecution functionExecution = getFunctionExecution()
.setArgs(args)
.setFunction(function)
.setTimeout(timeout);
return executeAndExtract(functionExecution);
}
@Override
public <T> Iterable<T> execute(String functionId, Object... args) {
FunctionExecution functionExecution = getFunctionExecution()
.setArgs(args)
.setFunctionId(functionId)
.setTimeout(timeout);
return execute(functionExecution);
}
@Override
public <T> T executeAndExtract(String functionId, Object... args) {
FunctionExecution functionExecution = getFunctionExecution()
.setArgs(args)
.setFunctionId(functionId)
.setTimeout(timeout);
return executeAndExtract(functionExecution);
}
@Override
public <T> T execute(GemfireFunctionCallback<T> callback) {
Execution execution = getFunctionExecution().getExecution();
return callback.doInGemfire(execution);
}
protected <T> Iterable<T> execute(FunctionExecution execution) {
execution.setTimeout(timeout);
return execution.execute();
}
protected <T> T executeAndExtract(FunctionExecution execution) {
execution.setTimeout(timeout);
return execution.executeAndExtract();
}
public void setTimeout(long timeout) {
this.timeout = timeout;
}
protected abstract FunctionExecution getFunctionExecution();
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2011 the original author or authors. * Copyright 2002-2012 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 * 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 * the License. You may obtain a copy of the License at
@@ -10,23 +10,20 @@
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 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. * specific language governing permissions and limitations under the License.
*/ */
package org.springframework.data.gemfire.function.foo; package org.springframework.data.gemfire.function.execution;
import java.util.List; import com.gemstone.gemfire.cache.execute.Execution;
import java.util.Map; import com.gemstone.gemfire.cache.execute.FunctionService;
/** /**
* @author David Turanski * @author David Turanski
* *
*/ */
public interface IFoo { public class AllMembersFunctionExecution extends FunctionExecution {
@Override
protected Execution getExecution() {
return FunctionService.onMembers();
}
public abstract Integer oneArg(String key); }
public abstract Integer twoArg(String akey, String bkey);
public abstract List<Integer> collections(List<Integer> args);
public abstract Map<String, Integer> getMapWithNoArgs();
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2002-2012 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.function.execution;
import java.lang.reflect.Method;
/**
* @author David Turanski
*
*/
class DefaultFunctionExecutionMethodMetadata extends FunctionExecutionMethodMetadata<MethodMetadata> {
/**
* @param serviceInterface
*/
public DefaultFunctionExecutionMethodMetadata(Class<?> serviceInterface) {
super(serviceInterface);
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.FunctionExecutionMethodMetadata#newMetadataInstance(java.lang.reflect.Method)
*/
@Override
protected MethodMetadata newMetadataInstance(Method method) {
return new MethodMetadata(method);
}
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2002-2012 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.function.execution;
import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.FunctionService;
/**
* @author David Turanski
*
*/
public class DefaultMemberFunctionExecution extends FunctionExecution {
@Override
protected Execution getExecution() {
return FunctionService.onMember();
}
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2011 the original author or authors. * Copyright 2002-2012 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 * 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 * the License. You may obtain a copy of the License at
@@ -10,41 +10,36 @@
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 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. * specific language governing permissions and limitations under the License.
*/ */
package org.springframework.data.gemfire.function; package org.springframework.data.gemfire.function.execution;
import java.io.Serializable; import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.execute.Execution; import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.Function;
import com.gemstone.gemfire.cache.execute.FunctionService; import com.gemstone.gemfire.cache.execute.FunctionService;
import com.gemstone.gemfire.distributed.DistributedSystem; import com.gemstone.gemfire.distributed.DistributedMember;
/** /**
* @author David Turanski * @author David Turanski
* *
*/ */
public class MembersFunctionExecution extends FunctionExecution<Object> { public class DistributedMemberFunctionExecution extends FunctionExecution {
private final DistributedSystem distributedSystem; private final DistributedMember distributedMember;
/** /**
* @param functionId *
* @param args * @param distributedMember
*/ */
public MembersFunctionExecution(DistributedSystem distributedSystem, Function function, Serializable... args) { public DistributedMemberFunctionExecution(DistributedMember distributedMember) {
super(function, args); super();
this.distributedSystem = distributedSystem; Assert.notNull(distributedMember);
this.distributedMember = distributedMember;
} }
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.FunctionExecution#getExecution()
*/
@Override @Override
protected Execution getExecution() { protected Execution getExecution() {
return FunctionService.onMembers(this.distributedSystem); return FunctionService.onMember(this.distributedMember);
} }
} }

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2002-2012 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.function.execution;
import java.util.Set;
import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.FunctionService;
import com.gemstone.gemfire.distributed.DistributedMember;
/**
* @author David Turanski
*
*/
public class DistributedMembersFunctionExecution extends FunctionExecution {
private final Set<DistributedMember> distributedMembers;
/**
*
* @param distributedMembers
*/
public DistributedMembersFunctionExecution(Set<DistributedMember> distributedMembers ) {
super( );
this.distributedMembers = distributedMembers;
}
@Override
protected Execution getExecution() {
return FunctionService.onMembers(this.distributedMembers);
}
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2011 the original author or authors. * Copyright 2002-2012 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 * 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 * the License. You may obtain a copy of the License at
@@ -10,10 +10,10 @@
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 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. * specific language governing permissions and limitations under the License.
*/ */
package org.springframework.data.gemfire.function; package org.springframework.data.gemfire.function.execution;
import java.io.Serializable; import java.util.ArrayList;
import java.util.List; import java.util.Iterator;
import java.util.Set; import java.util.Set;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
@@ -25,40 +25,47 @@ import org.springframework.util.StringUtils;
import com.gemstone.gemfire.cache.execute.Execution; import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.Function; import com.gemstone.gemfire.cache.execute.Function;
import com.gemstone.gemfire.cache.execute.FunctionException; import com.gemstone.gemfire.cache.execute.FunctionException;
import com.gemstone.gemfire.cache.execute.FunctionService;
import com.gemstone.gemfire.cache.execute.ResultCollector; import com.gemstone.gemfire.cache.execute.ResultCollector;
/** /**
* Base class for * Creating a GemFire {@link Execution} using {@link FunctionService}
* @author David Turanski * @author David Turanski
*/ */
public abstract class FunctionExecution<T> { public abstract class FunctionExecution {
protected final Log logger = LogFactory.getLog(this.getClass()); protected final Log logger = LogFactory.getLog(this.getClass());
private volatile ResultCollector<?, ?> collector; private volatile ResultCollector<?, ?> collector;
private final Serializable[] args; private Object[] args;
private Function function; private Function function;
private final String functionId; private String functionId;
private long timeout; private long timeout;
public FunctionExecution(Function function, Serializable... args) { public FunctionExecution(Function function, Object... args) {
Assert.notNull(function,"function cannot be null"); Assert.notNull(function,"function cannot be null");
this.function = function; this.function = function;
this.functionId = function.getId(); this.functionId = function.getId();
this.args = args; this.args = args;
} }
public FunctionExecution(String functionId, Serializable... args) { public FunctionExecution(String functionId, Object... args) {
Assert.isTrue(StringUtils.hasLength(functionId),"functionId cannot be null or empty"); Assert.isTrue(StringUtils.hasLength(functionId),"functionId cannot be null or empty");
this.functionId = functionId; this.functionId = functionId;
this.args = args; this.args = args;
} }
protected FunctionExecution() {
}
public ResultCollector<?, ?> getCollector() { public ResultCollector<?, ?> getCollector() {
return collector; return collector;
} }
public Serializable[] getArgs() { public Object[] getArgs() {
return args; return args;
} }
@@ -74,9 +81,10 @@ public abstract class FunctionExecution<T> {
this.collector = collector; this.collector = collector;
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public List<T> execute() { public <T> Iterable<T> execute() {
Execution execution = this.getExecution(); Execution execution = this.getExecution();
if (getKeys() != null) { if (getKeys() != null) {
execution = execution.withFilter(getKeys()); execution = execution.withFilter(getKeys());
@@ -96,9 +104,11 @@ public abstract class FunctionExecution<T> {
resultsCollector = (ResultCollector<?,?>) execution.execute(function); resultsCollector = (ResultCollector<?,?>) execution.execute(function);
} }
Iterable<T> results = null;
if (this.timeout > 0 ){ if (this.timeout > 0 ){
try { try {
return (List<T>)resultsCollector.getResult(this.timeout, TimeUnit.MILLISECONDS); results= (Iterable<T>)resultsCollector.getResult(this.timeout, TimeUnit.MILLISECONDS);
} }
catch (FunctionException e) { catch (FunctionException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
@@ -107,27 +117,52 @@ public abstract class FunctionExecution<T> {
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} else { } else {
return (List<T>)resultsCollector.getResult();
results = (Iterable<T>) resultsCollector.getResult();
} }
return replaceSingletonNullCollectionWithEmptyList(results);
} }
public T executeAndExtract() { public <T> T executeAndExtract() {
return this.execute().get(0); Iterable<T> results = this.execute();
if (results == null || !results.iterator().hasNext()) {
return null;
}
return results.iterator().next();
} }
protected abstract Execution getExecution(); protected abstract Execution getExecution();
protected FunctionExecution setFunctionId(String functionId) {
this.functionId = functionId;
return this;
}
protected FunctionExecution setFunction(Function function) {
this.function = function;
return this;
}
protected FunctionExecution setArgs(Object... args) {
this.args = args;
return this;
}
protected Set<?> getKeys() { protected Set<?> getKeys() {
return null; return null;
} }
public void setTimeout(long timeout) { public FunctionExecution setTimeout(long timeout) {
this.timeout = timeout; this.timeout = timeout;
return this;
} }
public long getTimeout() { public long getTimeout() {
return timeout; return timeout;
} }
/** /**
* @return * @return
@@ -135,5 +170,23 @@ public abstract class FunctionExecution<T> {
private boolean isRegisteredFunction() { private boolean isRegisteredFunction() {
return function == null; return function == null;
} }
private <T> Iterable<T> replaceSingletonNullCollectionWithEmptyList(Iterable<T> results) {
if (results == null) {
return results;
}
Iterator<T> it = results.iterator();
if (!it.hasNext()) {
return results;
}
if (it.next()==null && !it.hasNext()) {
return new ArrayList<T>();
}
return results;
}
} }

View File

@@ -0,0 +1,94 @@
/*
* Copyright 2002-2012 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.function.execution;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import org.springframework.data.gemfire.function.config.FunctionId;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
/**
* Base class for method level metadata for a function execution interface. This is used at runtime by the
* function execution proxy to create the corresponding Gemfire function {@link Execution}
*
* @author David Turanski
*
*/
abstract class FunctionExecutionMethodMetadata<T extends MethodMetadata > {
protected final Map<Method, T> methodMetadata = new HashMap<Method, T>();
private final boolean singletonInterface;
public FunctionExecutionMethodMetadata(final Class<?> serviceInterface) {
this.singletonInterface = serviceInterface.getMethods().length == 1;
ReflectionUtils.doWithMethods(serviceInterface, new ReflectionUtils.MethodCallback() {
@Override
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
T mmd = newMetadataInstance(method);
if (mmd.getFunctionId() == null) {
mmd.setFunctionId(serviceInterface.getName() + "." + method.getName());
}
methodMetadata.put(method, mmd);
}
});
}
protected abstract T newMetadataInstance(Method method);
T getMethodMetadata(Method method) {
return methodMetadata.get(method);
}
boolean isSingletonInterface() {
return this.singletonInterface;
}
T getSingletonMethodMetada() {
Assert.isTrue(isSingletonInterface(),"this is not a singleton interface.");
return methodMetadata.values().iterator().next();
}
}
class MethodMetadata {
private String functionId;
public MethodMetadata(Method method) {
String annotatedFunctionId = annotatedFunctionId(method);
this.functionId = (annotatedFunctionId == null) ? null : annotatedFunctionId;
}
/**
* @return the functionId
*/
public String getFunctionId() {
return functionId;
}
public void setFunctionId(String functionId) {
this.functionId = functionId;
}
private String annotatedFunctionId(Method method) {
FunctionId functionIdAnnotation = method.getAnnotation(FunctionId.class);
return (functionIdAnnotation == null) ? null : functionIdAnnotation.value();
}
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2011 the original author or authors. * Copyright 2002-2012 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 * 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 * the License. You may obtain a copy of the License at
@@ -10,11 +10,12 @@
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 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. * specific language governing permissions and limitations under the License.
*/ */
package org.springframework.data.gemfire.function; package org.springframework.data.gemfire.function.execution;
import com.gemstone.gemfire.cache.execute.Execution; import com.gemstone.gemfire.cache.execute.Execution;
/** /**
* A callback for Gemfire Function Templates
* @author David Turanski * @author David Turanski
* *
*/ */

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2002-2012 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.function.execution;
import com.gemstone.gemfire.cache.execute.Function;
/**
*
* An interface for invoking Gemfire functions
*
* @author David Turanski
*
* @param <T> the preferred return type
*/
public interface GemfireFunctionOperations {
/**
* Execute an unregistered function
* @param function the function
* @param args calling arguments
* @return the contents of the results collector
*/
public abstract <T> Iterable<T> execute(Function function, Object... args);
/**
* Execute an unregistered function with an expected singleton result
* @param function the function
* @param args calling arguments
* @return the first item in the results collector
*/
public abstract <T> T executeAndExtract(Function function, Object... args);
/**
* Execute a function registered with an ID
* @param functionId the function ID
* @param args the calling arguments
* @return the results
*/
public abstract <T> Iterable<T> execute(String functionId, Object... args);
/**
* Execute a function registered with an ID and with an expected singleton result
* @param functionId the function ID
* @param args the calling arguments
* @return the first item in the results collector
*/
public abstract <T> T executeAndExtract(String functionId, Object... args);
/**
* Execute a function using a native GemFire {@link Execution} instance
* @param callback a callback providing the execution instance
* @return the execution result
*/
public abstract <T> T execute(GemfireFunctionCallback<T> callback);
}

View File

@@ -0,0 +1,178 @@
/*
* Copyright 2002-2012 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.function.execution;
import java.lang.reflect.Method;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.gemfire.function.config.FunctionId;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import com.gemstone.gemfire.cache.execute.FunctionException;
/**
* A proxy Factory Bean for all non-region function execution interfaces
*
* @author David Turanski
*
*/
public class GemfireFunctionProxyFactoryBean implements FactoryBean<Object>, MethodInterceptor, BeanClassLoaderAware, InitializingBean {
protected volatile ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
protected final Class<?> serviceInterface;
protected volatile Object serviceProxy;
private volatile boolean initialized;
protected String functionId;
protected Log logger = LogFactory.getLog(this.getClass());
protected final GemfireFunctionOperations gemfireFunctionOperations;
private FunctionExecutionMethodMetadata<MethodMetadata> methodMetadata;
/**
* @param serviceInterface the proxied interface
* @param functionId the associated function id (must be a function registered by this id with the GemFire {@link FunctionService}
* @param gemfireFunctionOperations an interface used to delegate the function invocation (typically a GemFire function template)
*/
public GemfireFunctionProxyFactoryBean(Class<?> serviceInterface,
GemfireFunctionOperations gemfireFunctionOperations) {
Assert.notNull(serviceInterface, "'serviceInterface' must not be null");
Assert.isTrue(serviceInterface.isInterface(), "'serviceInterface' must be an interface");
this.serviceInterface = serviceInterface;
this.gemfireFunctionOperations = gemfireFunctionOperations;
this.methodMetadata = new DefaultFunctionExecutionMethodMetadata(serviceInterface);
}
protected Iterable<?> invokeFunction(Method method, Object[] args) {
MethodMetadata mmd = this.methodMetadata.getMethodMetadata(method);
return this.gemfireFunctionOperations.execute(mmd.getFunctionId(), args);
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
beanClassLoader = classLoader;
}
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
if (AopUtils.isToStringMethod(invocation.getMethod())) {
return "Gemfire function proxy for service interface [" + this.serviceInterface + "]";
}
if (logger.isDebugEnabled()) {
logger.debug("invoking method " + invocation.getMethod().getName());
}
Iterable<?> results = invokeFunction(invocation.getMethod(), invocation.getArguments());
return extractResult(results, invocation.getMethod().getReturnType());
}
@Override
public Object getObject() throws Exception {
if (this.serviceProxy == null) {
this.onInit();
Assert.notNull(this.serviceProxy, "failed to initialize proxy");
}
return this.serviceProxy;
}
@Override
public Class<?> getObjectType() {
return (this.serviceInterface != null ? this.serviceInterface : null);
}
@Override
public boolean isSingleton() {
return true;
}
protected void onInit() {
if (this.initialized) {
return;
}
ProxyFactory proxyFactory = new ProxyFactory(serviceInterface, this);
this.serviceProxy = proxyFactory.getProxy(this.beanClassLoader);
this.initialized = true;
}
protected String annotatedFunctionId(Method method) {
FunctionId functionIdAnnotation = method.getAnnotation(FunctionId.class);
return (functionIdAnnotation == null) ? null: functionIdAnnotation.value();
}
/**
* Optional to set a default function Id for a single method interface with no {code}@FunctionId{code} annotations
* @param functionId
*/
protected void setFunctionId(String functionId) {
this.functionId = functionId;
}
/*
* Match the result to the declared return type
*/
private Object extractResult(Iterable<?> results, Class<?> returnType) {
Object result = null;
if (results != null) {
if (Iterable.class.isAssignableFrom(returnType)) {
result = results;
} else {
int nonNullItems = 0;
for (Object obj : results) {
if (obj != null) {
if (++nonNullItems > 1) {
throw new FunctionException("multiple results found for single valued return type");
} else {
result = obj;
}
}
}
}
if (logger.isDebugEnabled()) {
logger.debug("returning result as " + result.getClass().getName());
}
}
return result;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@Override
public void afterPropertiesSet() throws Exception {
if (this.functionId != null) {
Assert.isTrue(this.methodMetadata.isSingletonInterface(), "cannot assign default function id if interface has multiple methods");
this.methodMetadata.getSingletonMethodMetada().setFunctionId(this.functionId);
}
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2002-2012 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.function.execution;
import com.gemstone.gemfire.distributed.DistributedMember;
/**
*
* @author David Turanski
*
*/
public class GemfireOnMemberFunctionTemplate extends AbstractFunctionTemplate {
private final DistributedMember distributedMember;
private final String[] groups;
public GemfireOnMemberFunctionTemplate (DistributedMember distributedMember) {
this.distributedMember = distributedMember;
this.groups = null;
}
public GemfireOnMemberFunctionTemplate (String[] groups) {
this.distributedMember = null;
this.groups = groups;
}
public GemfireOnMemberFunctionTemplate () {
this.distributedMember = null;
this.groups = null;
}
protected FunctionExecution getFunctionExecution() {
if (distributedMember == null && groups == null) {
return new DefaultMemberFunctionExecution();
} else if (distributedMember == null) {
return new GroupMemberFunctionExecution(this.groups);
}
return new DistributedMemberFunctionExecution(this.distributedMember);
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2002-2012 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.function.execution;
import java.util.Set;
import com.gemstone.gemfire.distributed.DistributedMember;
/**
* @author David Turanski
*
*/
public class GemfireOnMembersFunctionTemplate extends AbstractFunctionTemplate {
private final Set<DistributedMember> distributedMembers;
private final String[] groups;
GemfireOnMembersFunctionTemplate (Set<DistributedMember> distributedMembers) {
this.distributedMembers = distributedMembers;
this.groups = null;
}
GemfireOnMembersFunctionTemplate (String[] groups) {
this.distributedMembers = null;
this.groups = groups;
}
GemfireOnMembersFunctionTemplate () {
this.distributedMembers = null;
this.groups = null;
}
protected FunctionExecution getFunctionExecution() {
if (distributedMembers == null && groups == null) {
return new AllMembersFunctionExecution();
} else if (distributedMembers == null) {
return new GroupMembersFunctionExecution(this.groups);
}
return new DistributedMembersFunctionExecution(this.distributedMembers);
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2002-2012 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.function.execution;
import java.util.Set;
import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.execute.Function;
/**
* @author David Turanski
*
*/
public class GemfireOnRegionFunctionTemplate extends AbstractFunctionTemplate implements GemfireOnRegionOperations {
private Region<?, ?> region;
/**
*
* @param region
*/
public GemfireOnRegionFunctionTemplate(Region<?,?> region) {
Assert.notNull(region, "Region cannot be null");
this.region = region;
}
@Override
public <T> Iterable<T> execute(Function function, Set<?> keys, Object... args) {
return execute(new RegionFunctionExecution(region)
.setKeys(keys)
.setFunction(function)
.setTimeout(timeout)
.setArgs(args) );
}
@Override
public <T> Iterable<T> execute(String functionId, Set<?> keys, Object... args) {
return execute(new RegionFunctionExecution(region)
.setKeys(keys)
.setFunctionId(functionId)
.setTimeout(timeout)
.setArgs(args) );
}
@Override
public <T> T executeAndextract(String functionId, Set<?> keys, Object... args) {
return executeAndExtract(new RegionFunctionExecution(region)
.setKeys(keys)
.setFunctionId(functionId)
.setTimeout(timeout)
.setArgs(args) );
}
@Override
protected FunctionExecution getFunctionExecution() {
return new RegionFunctionExecution(this.region);
}
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2002-2012 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.function.execution;
import java.util.Set;
import com.gemstone.gemfire.cache.execute.Function;
/**
* @author David Turanski
*
* @param <T>
*/
public interface GemfireOnRegionOperations extends GemfireFunctionOperations {
public abstract <T> Iterable<T> execute(String functionId, Set<?> keys, Object... args);
public abstract <T> Iterable<T> execute(Function function, Set<?> keys, Object... args);
public abstract <T> T executeAndextract(String functionId, Set<?> keys, Object... args);
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2002-2012 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.function.execution;
import com.gemstone.gemfire.cache.RegionService;
import com.gemstone.gemfire.cache.client.Pool;
/**
* @author David Turanski
*
*/
public class GemfireOnServerFunctionTemplate extends AbstractFunctionTemplate {
private final RegionService cache;
private final Pool pool;
GemfireOnServerFunctionTemplate (RegionService cache) {
this.cache = cache;
this.pool = null;
}
GemfireOnServerFunctionTemplate (Pool pool) {
this.pool = pool;
this.cache = null;
}
@Override
protected FunctionExecution getFunctionExecution() {
if (this.pool == null) {
return new ServerFunctionExecution(this.cache);
}
return new PoolServerFunctionExecution(this.pool);
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2002-2012 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.function.execution;
import com.gemstone.gemfire.cache.RegionService;
import com.gemstone.gemfire.cache.client.Pool;
/**
* @author David Turanski
*
*/
public class GemfireOnServersFunctionTemplate extends AbstractFunctionTemplate {
private final RegionService cache;
private final Pool pool;
GemfireOnServersFunctionTemplate (RegionService cache) {
this.cache = cache;
this.pool = null;
}
GemfireOnServersFunctionTemplate (Pool pool) {
this.pool = pool;
this.cache = null;
}
@Override
protected FunctionExecution getFunctionExecution() {
if (this.pool == null) {
return new ServersFunctionExecution(this.cache);
}
return new PoolServersFunctionExecution(this.pool);
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright 2002-2012 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.function.execution;
import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.FunctionService;
/**
* @author David Turanski
*
*/
public class GroupMemberFunctionExecution extends FunctionExecution {
private final String groups[];
/**
*
* @param groups
*/
public GroupMemberFunctionExecution(String... groups) {
super();
Assert.notEmpty(groups, "groups cannot be null or empty.");
this.groups = groups;
}
@Override
protected Execution getExecution() {
return FunctionService.onMember(this.groups);
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright 2002-2012 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.function.execution;
import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.FunctionService;
/**
* @author David Turanski
*
*/
public class GroupMembersFunctionExecution extends FunctionExecution {
private final String groups[];
/**
*
* @param groups
*/
public GroupMembersFunctionExecution(String... groups) {
super();
Assert.notEmpty(groups, "groups cannot be null or empty.");
this.groups = groups;
}
@Override
protected Execution getExecution() {
return FunctionService.onMember(this.groups);
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright 2002-2012 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.function.execution;
import java.lang.reflect.Method;
import java.util.Set;
import org.springframework.data.gemfire.function.config.Filter;
import org.springframework.data.gemfire.function.config.GemfireFunctionUtils;
/**
* @author David Turanski
*
*/
class OnRegionExecutionMethodMetadata extends FunctionExecutionMethodMetadata<OnRegionMethodMetadata> {
/**
* @param serviceInterface
*/
public OnRegionExecutionMethodMetadata(Class<?> serviceInterface) {
super(serviceInterface);
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.FunctionExecutionMethodMetadata#newMetadataInstance(java.lang.reflect.Method)
*/
@Override
protected OnRegionMethodMetadata newMetadataInstance(Method method) {
return new OnRegionMethodMetadata(method);
}
}
class OnRegionMethodMetadata extends MethodMetadata {
private final int filterArgPosition;
public OnRegionMethodMetadata(Method method) {
super(method);
this.filterArgPosition = GemfireFunctionUtils.getAnnotationParameterPosition(method, Filter.class, new Class<?>[]{Set.class});
}
public int getFilterArgPosition() {
return this.filterArgPosition;
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2002-2012 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.function.execution;
import java.lang.reflect.Method;
import java.util.Set;
import org.springframework.data.gemfire.util.ArrayUtils;
/**
* @author David Turanski
*
*/
public class OnRegionFunctionProxyFactoryBean extends GemfireFunctionProxyFactoryBean {
private OnRegionExecutionMethodMetadata methodMetadata;
/**
* @param serviceInterface
* @param gemfireOnRegionOperations an {@link GemfireOnRegionOperations} instance
*/
public OnRegionFunctionProxyFactoryBean(Class<?> serviceInterface,
GemfireOnRegionOperations gemfireOnRegionOperations) {
super(serviceInterface, (GemfireFunctionOperations) gemfireOnRegionOperations);
methodMetadata = new OnRegionExecutionMethodMetadata(serviceInterface);
}
@Override
protected Iterable<?> invokeFunction(Method method, Object[] args) {
Set<?> filter = null;
Iterable<?> results = null;
GemfireOnRegionOperations gemfireOnRegionOperations = (GemfireOnRegionOperations) this.gemfireFunctionOperations;
OnRegionMethodMetadata ormmd = methodMetadata.getMethodMetadata(method);
int filterArgPosition = ormmd.getFilterArgPosition();
String functionId = ormmd.getFunctionId();
/*
* extract filter from args if necessary
*/
if (filterArgPosition >=0 ) {
filter = (Set<?>)args[filterArgPosition];
args = ArrayUtils.remove(args, filterArgPosition);
}
if (filter == null) {
results = gemfireOnRegionOperations.execute(functionId, args);
} else {
results = gemfireOnRegionOperations.execute(functionId, filter, args);
}
return results;
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2002-2012 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.function.execution;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.client.ClientCache;
import com.gemstone.gemfire.cache.client.Pool;
import com.gemstone.gemfire.cache.client.PoolManager;
import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.FunctionService;
/**
* Creates a GemFire {@link Execution} using {code}FunctionService.onServer(Pool pool){code}
* @author David Turanski
*
*/
public class PoolServerFunctionExecution extends FunctionExecution implements InitializingBean {
private Pool pool;
private String poolname;
/**
* @param pool the {@link Pool}
*/
public PoolServerFunctionExecution(Pool pool) {
super();
Assert.notNull(pool, "pool cannot be null");
this.pool = pool;
}
public PoolServerFunctionExecution(String poolname) {
super();
Assert.notNull(poolname, "pool name cannot be null");
this.poolname = poolname;
}
@Override
protected Execution getExecution() {
return FunctionService.onServer(this.pool);
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@Override
public void afterPropertiesSet() throws Exception {
this.pool = PoolManager.find(poolname);
Assert.notNull(pool," pool " + poolname+ " does not exist");
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2002-2012 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.function.execution;
import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.client.Pool;
import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.FunctionService;
/**
* Creates a GemFire {@link Execution} using {code}FunctionService.onServers(Pool pool){code}
* @author David Turanski
*
*/
public class PoolServersFunctionExecution extends FunctionExecution {
private final Pool pool;
/**
* @param pool the {@link Pool}
*/
public PoolServersFunctionExecution(Pool pool ) {
super();
Assert.notNull(pool, "pool cannot be null");
this.pool = pool;
}
@Override
protected Execution getExecution() {
return FunctionService.onServers(this.pool);
}
}

View File

@@ -10,38 +10,35 @@
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 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. * specific language governing permissions and limitations under the License.
*/ */
package org.springframework.data.gemfire.function; package org.springframework.data.gemfire.function.execution;
import java.io.Serializable;
import java.util.Set; import java.util.Set;
import org.springframework.util.CollectionUtils;
import com.gemstone.gemfire.cache.Region; import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.execute.Execution; import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.Function;
import com.gemstone.gemfire.cache.execute.FunctionService; import com.gemstone.gemfire.cache.execute.FunctionService;
/** /**
* Creates a GemFire {@link Execution} using {code}FunctionService.onRegion(Region region){code}
* @author David Turanski * @author David Turanski
* *
*/ */
public class RegionFunctionExecution<T> extends FunctionExecution<T> { public class RegionFunctionExecution extends FunctionExecution {
private final Region<?, ?> region; private final Region<?, ?> region;
private volatile Set<?> keys; private volatile Set<?> keys;
public RegionFunctionExecution(Region<?, ?> region, Function function, Serializable... args) { public RegionFunctionExecution(Region<?, ?> region) {
super(function, args); super();
this.region = region; this.region = region;
} }
public RegionFunctionExecution(Region<?, ?> region, String functionId, Serializable... args) { public RegionFunctionExecution setKeys(Set<?> keys) {
super(functionId, args);
this.region = region;
}
public void setKeys(Set<?> keys) {
this.keys = keys; this.keys = keys;
return this;
} }
protected Set<?> getKeys() { protected Set<?> getKeys() {
@@ -53,6 +50,10 @@ public class RegionFunctionExecution<T> extends FunctionExecution<T> {
*/ */
@Override @Override
protected Execution getExecution() { protected Execution getExecution() {
return FunctionService.onRegion(region); Execution execution = FunctionService.onRegion(region);
if (!CollectionUtils.isEmpty(this.keys) ) {
execution = execution.withFilter(keys);
}
return execution;
} }
} }

View File

@@ -0,0 +1,43 @@
/*
* Copyright 2002-2012 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.function.execution;
import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.RegionService;
import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.FunctionService;
/**
* Creates a GemFire {@link Execution} using {code}FunctionService.onServer(RegionService regionService){code}
* @author David Turanski
*
*/
public class ServerFunctionExecution extends FunctionExecution {
private RegionService regionService;
public ServerFunctionExecution(RegionService regionService) {
super();
Assert.notNull(regionService,"regionService cannot be null");
this.regionService = regionService;
}
@Override
protected Execution getExecution() {
return FunctionService.onServer(this.regionService);
}
}

View File

@@ -1,5 +1,5 @@
/* /*
* Copyright 2002-2011 the original author or authors. * Copyright 2002-2012 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 * 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 * the License. You may obtain a copy of the License at
@@ -10,20 +10,20 @@
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the * 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. * specific language governing permissions and limitations under the License.
*/ */
package org.springframework.data.gemfire.function; package org.springframework.data.gemfire.function.execution;
import java.io.Serializable; import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.RegionService; import com.gemstone.gemfire.cache.RegionService;
import com.gemstone.gemfire.cache.execute.Execution; import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.Function;
import com.gemstone.gemfire.cache.execute.FunctionService; import com.gemstone.gemfire.cache.execute.FunctionService;
/** /**
* Creates a GemFire {@link Execution} using {code}FunctionService.onServers(RegionService regionService){code}
* @author David Turanski * @author David Turanski
* *
*/ */
public class ServersFunctionExecution<T> extends FunctionExecution<T> { public class ServersFunctionExecution extends FunctionExecution {
private final RegionService regionService; private final RegionService regionService;
@@ -34,25 +34,12 @@ public class ServersFunctionExecution<T> extends FunctionExecution<T> {
* @param function * @param function
* @param args * @param args
*/ */
public ServersFunctionExecution(RegionService regionService, Function function, Serializable... args) { public ServersFunctionExecution(RegionService regionService ) {
super(function, args); super();
this.regionService = regionService; Assert.notNull(regionService,"regionService cannot be null");
}
/**
*
* @param regionService e.g., Cache,Client, or GemFireCache
* @param functionId
* @param args
*/
public ServersFunctionExecution(RegionService regionService, String functionId, Serializable... args) {
super(functionId, args);
this.regionService = regionService; this.regionService = regionService;
} }
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.FunctionExecution#getExecution()
*/
@Override @Override
protected Execution getExecution() { protected Execution getExecution() {
return FunctionService.onServers(this.regionService); return FunctionService.onServers(this.regionService);

View File

@@ -176,7 +176,7 @@ public class AsmInstantiatorGenerator implements InstantiatorGenerator, Opcodes
} }
byte[] generateClassBytecode(String className, Class<? extends DataSerializable> clazz, int classId) { byte[] generateClassBytecode(String className, Class<? extends DataSerializable> clazz, int classId) {
ClassWriter cw = new ClassWriter(false); ClassWriter cw = new ClassWriter(0);
cw.visit(V1_5, ACC_PUBLIC + ACC_SUPER, className, null, INSTANTIATOR_NAME, new String[] { SERIALIZABLE_NAME }); 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, FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL + ACC_STATIC, CLASS_FIELD_NAME, CLASS_DESCRIPTOR, null,

View File

@@ -0,0 +1,88 @@
/*
* Copyright 2002-2012 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.util;
/**
* @author David Turanski
*
*/
public abstract class ArrayUtils {
/**
* Insert an element into an array. The element is inserted at the
* given position, all elements afterwards are moved to the right.
*
* @param originalArray array to insert into
* @param pos position at which to insert the element
* @param element element to add
* @return the new array
*/
public static Object[] insert(Object[] originalArray, int pos, Object element) {
Object[] newArray = (Object[]) java.lang.reflect.Array.newInstance(
originalArray.getClass().getComponentType(), originalArray.length + 1);
// copy everything before the given position
if (pos > 0) {
System.arraycopy(originalArray, 0, newArray, 0, pos); // does not copy originalArray[pos], where we insert
}
// insert
newArray[pos] = element;
// copy remaining elements
if (pos < originalArray.length) {
System.arraycopy(originalArray, pos, // originalArray[pos] first element copied
newArray, pos + 1, // newArray[pos + 1] first destination
originalArray.length - pos); // number of elements left
}
return newArray;
}
/**
* Remove element from an array. The element is removed at the
* specified position, and all remaining elements are moved to the left.
*
* @param originalArray array to remove from
* @param pos position to remove
* @return the new array
*/
public static Object[] remove(Object[] originalArray, int pos) {
Object[] newArray = (Object[])java.lang.reflect.Array.newInstance(
originalArray.getClass().getComponentType(), originalArray.length - 1);
// Copy everything before
if (pos > 0) {
System.arraycopy(originalArray, 0, newArray, 0, pos); // originalArray[pos - 1] is last element copied
}
// Copy everything after
if (pos < originalArray.length - 1) {
System.arraycopy(originalArray, pos + 1, // originalArray[pos + 1] is first element copied
newArray, pos, // first position to copy into
originalArray.length - 1 - pos);
}
return newArray;
}
}

View File

@@ -34,15 +34,25 @@ public abstract class AbstractWANComponentFactoryBean<T> implements FactoryBean<
DisposableBean { DisposableBean {
protected Log log = LogFactory.getLog(this.getClass()); protected Log log = LogFactory.getLog(this.getClass());
protected String name; private String name;
protected final Cache cache; protected final Cache cache;
protected Object factory; protected Object factory;
private String beanName;
protected AbstractWANComponentFactoryBean(Cache cache) { protected AbstractWANComponentFactoryBean(Cache cache) {
this.cache = cache; this.cache = cache;
} }
public void setName(String name) {
this.name = name;
}
public String getName() {
return name!=null ? name: beanName;
}
@Override @Override
public void destroy() throws Exception { public void destroy() throws Exception {
@@ -50,13 +60,13 @@ public abstract class AbstractWANComponentFactoryBean<T> implements FactoryBean<
} }
@Override @Override
public final void setBeanName(String name) { public final void setBeanName(String beanName) {
this.name = name; this.beanName = beanName;
} }
@Override @Override
public final void afterPropertiesSet() throws Exception { public final void afterPropertiesSet() throws Exception {
Assert.notNull(name, "Name cannot be null"); Assert.notNull(getName(), "Name cannot be null");
Assert.notNull(cache, "Cache cannot be null"); Assert.notNull(cache, "Cache cannot be null");
doInit(); doInit();
} }

View File

@@ -92,7 +92,7 @@ public class AsyncEventQueueFactoryBean extends AbstractWANComponentFactoryBean<
asyncEventQueueFactory.setMaximumQueueMemory(maximumQueueMemory); asyncEventQueueFactory.setMaximumQueueMemory(maximumQueueMemory);
} }
asyncEventQueue = asyncEventQueueFactory.create(name, asyncEventListener); asyncEventQueue = asyncEventQueueFactory.create(getName(), asyncEventListener);
} }
@Override @Override

View File

@@ -76,6 +76,7 @@ public class GatewayHubFactoryBean extends AbstractWANComponentFactoryBean<Gatew
@Override @Override
protected void doInit() { protected void doInit() {
String name = getName();
gatewayHub = cache.addGatewayHub(name, port == null ? GatewayHub.DEFAULT_PORT : port); gatewayHub = cache.addGatewayHub(name, port == null ? GatewayHub.DEFAULT_PORT : port);
if (log.isDebugEnabled()) { if (log.isDebugEnabled()) {

View File

@@ -52,8 +52,6 @@ public class GatewayReceiverFactoryBean extends AbstractWANComponentFactoryBean<
*/ */
public GatewayReceiverFactoryBean(Cache cache) { public GatewayReceiverFactoryBean(Cache cache) {
super(cache); super(cache);
// Bean name not required.
this.name = "gateway-receiver";
} }
@Override @Override

View File

@@ -33,7 +33,7 @@ import com.gemstone.gemfire.cache.wan.GatewayTransportFilter;
* @author David Turanski * @author David Turanski
* *
*/ */
public class GatewaySenderFactoryBean extends AbstractWANComponentFactoryBean<GatewaySender> { public class GatewaySenderFactoryBean extends AbstractWANComponentFactoryBean<GatewaySender> {
private static List<String> validOrderPolicyValues = Arrays.asList("KEY", "PARTITION", "THREAD"); private static List<String> validOrderPolicyValues = Arrays.asList("KEY", "PARTITION", "THREAD");
private GatewaySender gatewaySender; private GatewaySender gatewaySender;
@@ -58,7 +58,7 @@ public class GatewaySenderFactoryBean extends AbstractWANComponentFactoryBean<Ga
private Integer dispatcherThreads; private Integer dispatcherThreads;
private Boolean manualStart; private boolean manualStart = false;
private Integer maximumQueueMemory; private Integer maximumQueueMemory;
@@ -82,12 +82,12 @@ public class GatewaySenderFactoryBean extends AbstractWANComponentFactoryBean<Ga
@Override @Override
public GatewaySender getObject() throws Exception { public GatewaySender getObject() throws Exception {
return gatewaySender; return new SmartLifecycleGatewaySender(gatewaySender, !manualStart);
} }
@Override @Override
public Class<?> getObjectType() { public Class<?> getObjectType() {
return GatewaySender.class; return SmartLifecycleGatewaySender.class;
} }
@Override @Override
@@ -151,9 +151,9 @@ public class GatewaySenderFactoryBean extends AbstractWANComponentFactoryBean<Ga
if (dispatcherThreads != null) { if (dispatcherThreads != null) {
gatewaySenderFactory.setDispatcherThreads(dispatcherThreads); gatewaySenderFactory.setDispatcherThreads(dispatcherThreads);
} }
if (manualStart != null) {
gatewaySenderFactory.setManualStart(manualStart); gatewaySenderFactory.setManualStart(true);
}
if (maximumQueueMemory != null) { if (maximumQueueMemory != null) {
gatewaySenderFactory.setMaximumQueueMemory(maximumQueueMemory); gatewaySenderFactory.setMaximumQueueMemory(maximumQueueMemory);
} }
@@ -163,7 +163,7 @@ public class GatewaySenderFactoryBean extends AbstractWANComponentFactoryBean<Ga
if (socketReadTimeout != null) { if (socketReadTimeout != null) {
gatewaySenderFactory.setSocketReadTimeout(socketReadTimeout); gatewaySenderFactory.setSocketReadTimeout(socketReadTimeout);
} }
gatewaySender = gatewaySenderFactory.create(name, remoteDistributedSystemId); gatewaySender = gatewaySenderFactory.create(getName(), remoteDistributedSystemId);
} }
public void setRemoteDistributedSystemId(int remoteDistributedSystemId) { public void setRemoteDistributedSystemId(int remoteDistributedSystemId) {
@@ -233,5 +233,4 @@ public class GatewaySenderFactoryBean extends AbstractWANComponentFactoryBean<Ga
public void setSocketReadTimeout(Integer socketReadTimeout) { public void setSocketReadTimeout(Integer socketReadTimeout) {
this.socketReadTimeout = socketReadTimeout; this.socketReadTimeout = socketReadTimeout;
} }
} }

View File

@@ -0,0 +1,277 @@
/*
* Copyright 2002-2012 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.wan;
import java.util.List;
import org.springframework.context.SmartLifecycle;
import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.util.Gateway.OrderPolicy;
import com.gemstone.gemfire.cache.wan.GatewayEventFilter;
import com.gemstone.gemfire.cache.wan.GatewaySender;
import com.gemstone.gemfire.cache.wan.GatewayTransportFilter;
/**
* A {@link GatewaySender} controlled by {@link SmartLifecycle}
* @author David Turanski
*
*/
public class SmartLifecycleGatewaySender implements GatewaySender, SmartLifecycle {
private final GatewaySender delegate;
private final boolean autoStartup;
public SmartLifecycleGatewaySender(GatewaySender delegate, boolean autoStartup) {
Assert.notNull(delegate);
this.delegate = delegate;
this.autoStartup = autoStartup;
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#addGatewayEventFilter(com.gemstone.gemfire.cache.wan.GatewayEventFilter)
*/
@Override
public void addGatewayEventFilter(GatewayEventFilter eventFilter) {
this.delegate.addGatewayEventFilter(eventFilter);
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#getAlertThreshold()
*/
@Override
public int getAlertThreshold() {
return this.delegate.getAlertThreshold();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#getBatchSize()
*/
@Override
public int getBatchSize() {
return this.delegate.getBatchSize();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#getBatchTimeInterval()
*/
@Override
public int getBatchTimeInterval() {
return this.delegate.getBatchTimeInterval();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#getDiskStoreName()
*/
@Override
public String getDiskStoreName() {
return this.delegate.getDiskStoreName();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#getDispatcherThreads()
*/
@Override
public int getDispatcherThreads() {
return this.delegate.getDispatcherThreads();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#getGatewayEventFilters()
*/
@Override
public List<GatewayEventFilter> getGatewayEventFilters() {
return this.delegate.getGatewayEventFilters();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#getGatewayTransportFilters()
*/
@Override
public List<GatewayTransportFilter> getGatewayTransportFilters() {
return this.delegate.getGatewayTransportFilters();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#getId()
*/
@Override
public String getId() {
return this.delegate.getId();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#getMaximumQueueMemory()
*/
@Override
public int getMaximumQueueMemory() {
return this.delegate.getMaximumQueueMemory();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#getOrderPolicy()
*/
@Override
public OrderPolicy getOrderPolicy() {
return this.delegate.getOrderPolicy();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#getRemoteDSId()
*/
@Override
public int getRemoteDSId() {
return this.delegate.getRemoteDSId();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#getSocketBufferSize()
*/
@Override
public int getSocketBufferSize() {
return this.delegate.getSocketBufferSize();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#getSocketReadTimeout()
*/
@Override
public int getSocketReadTimeout() {
return this.delegate.getSocketReadTimeout();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#isBatchConflationEnabled()
*/
@Override
public boolean isBatchConflationEnabled() {
return this.delegate.isBatchConflationEnabled();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#isDiskSynchronous()
*/
@Override
public boolean isDiskSynchronous() {
return this.delegate.isDiskSynchronous();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#isManualStart()
*/
@Override
public boolean isManualStart() {
return true;
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#isParallel()
*/
@Override
public boolean isParallel() {
return this.delegate.isParallel();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#isPaused()
*/
@Override
public boolean isPaused() {
return this.delegate.isPaused();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#isPersistenceEnabled()
*/
@Override
public boolean isPersistenceEnabled() {
return this.delegate.isPersistenceEnabled();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#isRunning()
*/
@Override
public boolean isRunning() {
return this.delegate.isRunning();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#pause()
*/
@Override
public void pause() {
this.delegate.pause();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#removeGatewayEventFilter(com.gemstone.gemfire.cache.wan.GatewayEventFilter)
*/
@Override
public void removeGatewayEventFilter(GatewayEventFilter eventFilter) {
this.delegate.removeGatewayEventFilter(eventFilter);
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#resume()
*/
@Override
public void resume() {
this.delegate.resume();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#start()
*/
@Override
public void start() {
this.delegate.start();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#stop()
*/
@Override
public void stop() {
this.delegate.stop();
}
/* (non-Javadoc)
* @see org.springframework.context.Phased#getPhase()
*/
@Override
public int getPhase() {
return Integer.MAX_VALUE;
}
/* (non-Javadoc)
* @see org.springframework.context.SmartLifecycle#isAutoStartup()
*/
@Override
public boolean isAutoStartup() {
return this.autoStartup ;
}
/* (non-Javadoc)
* @see org.springframework.context.SmartLifecycle#stop(java.lang.Runnable)
*/
@Override
public void stop(Runnable callback) {
stop();
callback.run();
}
}

View File

@@ -2,15 +2,20 @@
<xsd:schema xmlns="http://www.springframework.org/schema/data/gemfire" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans" <xsd:schema xmlns="http://www.springframework.org/schema/data/gemfire" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tool="http://www.springframework.org/schema/tool" xmlns:tool="http://www.springframework.org/schema/tool"
xmlns:repository="http://www.springframework.org/schema/data/repository" xmlns:repository="http://www.springframework.org/schema/data/repository"
xmlns:context="http://www.springframework.org/schema/context"
targetNamespace="http://www.springframework.org/schema/data/gemfire" elementFormDefault="qualified" attributeFormDefault="unqualified" version="1.3"> targetNamespace="http://www.springframework.org/schema/data/gemfire" elementFormDefault="qualified" attributeFormDefault="unqualified" version="1.3">
<xsd:import namespace="http://www.springframework.org/schema/beans"/> <xsd:import namespace="http://www.springframework.org/schema/beans"/>
<xsd:import namespace="http://www.springframework.org/schema/tool"/> <xsd:import namespace="http://www.springframework.org/schema/tool"/>
<xsd:import namespace="http://www.springframework.org/schema/data/repository" schemaLocation="http://www.springframework.org/schema/data/repository/spring-repository.xsd"/> <xsd:import namespace="http://www.springframework.org/schema/data/repository"
<xsd:import namespace="http://www.springframework.org/schema/gemfire" schemaLocation="http://www.springframework.org/schema/gemfire/spring-gemfire.xsd"/> schemaLocation="http://www.springframework.org/schema/data/repository/spring-repository.xsd"/>
<xsd:import namespace="http://www.springframework.org/schema/gemfire"
schemaLocation="http://www.springframework.org/schema/gemfire/spring-gemfire.xsd"/>
<xsd:import namespace="http://www.springframework.org/schema/context"
schemaLocation="http://www.springframework.org/schema/context/spring-context.xsd" />
<!-- --> <!-- -->
<xsd:annotation> <xsd:annotation>
<xsd:documentation><![CDATA[ <xsd:documentation><![CDATA[
Namespace support for the Spring Data GemFire Repositories. Namespace support for the Spring Data GemFire Client side data access.
]]></xsd:documentation> ]]></xsd:documentation>
</xsd:annotation> </xsd:annotation>
<!-- --> <!-- -->
@@ -26,6 +31,32 @@ targetNamespace="http://www.springframework.org/schema/data/gemfire" elementForm
</xsd:complexType> </xsd:complexType>
</xsd:element> </xsd:element>
<!-- --> <!-- -->
<xsd:complexType name="functions">
<xsd:sequence>
<xsd:element name="include-filter" type="context:filterType" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation><![CDATA[
Controls which eligible types to include for component scanning.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
<xsd:element name="exclude-filter" type="context:filterType" minOccurs="0" maxOccurs="unbounded">
<xsd:annotation>
<xsd:documentation><![CDATA[
Controls which eligible types to exclude for component scanning.
]]></xsd:documentation>
</xsd:annotation>
</xsd:element>
</xsd:sequence>
<xsd:attribute name="base-package" type="xsd:string" use="required">
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines the base package where function execution interfaces will be tried to be detected.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
</xsd:complexType>
<!-- -->
<xsd:attributeGroup name="gemfire-repository-attributes"> <xsd:attributeGroup name="gemfire-repository-attributes">
<xsd:attribute name="mapping-context-ref" type="mappingContextRef"> <xsd:attribute name="mapping-context-ref" type="mappingContextRef">
<xsd:annotation> <xsd:annotation>

View File

@@ -2250,6 +2250,13 @@ Inner bean definition of the event filter
minOccurs="0" maxOccurs="1" /> minOccurs="0" maxOccurs="1" />
</xsd:sequence> </xsd:sequence>
<xsd:attributeGroup ref="commonWANQueueAttributes" /> <xsd:attributeGroup ref="commonWANQueueAttributes" />
<xsd:attribute name="name" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Optionally specifies the GemFire gateway sender id. By default this value is the bean id or a generated value if an inner bean.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attribute name="remote-distributed-system-id" <xsd:attribute name="remote-distributed-system-id"
type="xsd:string" use="required"> type="xsd:string" use="required">
<xsd:annotation> <xsd:annotation>
@@ -2497,6 +2504,13 @@ use inner bean declarations.
</xsd:complexType> </xsd:complexType>
</xsd:element> </xsd:element>
</xsd:sequence> </xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="optional">
<xsd:annotation>
<xsd:documentation><![CDATA[
Optionally specifies the GemFire async event queue id. By default this value is the bean id or a generated value if an inner bean.
]]></xsd:documentation>
</xsd:annotation>
</xsd:attribute>
<xsd:attributeGroup ref="commonWANQueueAttributes" /> <xsd:attributeGroup ref="commonWANQueueAttributes" />
</xsd:complexType> </xsd:complexType>
<!-- --> <!-- -->

View File

@@ -32,8 +32,10 @@ import java.util.concurrent.atomic.AtomicBoolean;
public class ForkUtil { public class ForkUtil {
private static OutputStream os; private static OutputStream os;
private static String TEMP_DIR = System.getProperty("java.io.tmpdir"); private static String TEMP_DIR = System.getProperty("java.io.tmpdir");
public static OutputStream cloneJVM(String argument) { public static OutputStream cloneJVM(String arguments) {
String cp = System.getProperty("java.class.path"); String cp = System.getProperty("java.class.path");
String home = System.getProperty("java.home"); String home = System.getProperty("java.home");
@@ -41,9 +43,9 @@ public class ForkUtil {
String sp = System.getProperty("file.separator"); String sp = System.getProperty("file.separator");
String java = home + sp + "bin" + sp + "java"; String java = home + sp + "bin" + sp + "java";
String argCp = " -cp " + cp; String argCp = " -cp " + cp;
String argClass = argument;
String cmd = java + argCp + " " + argClass; String cmd = java + argCp + " " + arguments;
try { try {
//ProcessBuilder builder = new ProcessBuilder(cmd, argCp, argClass); //ProcessBuilder builder = new ProcessBuilder(cmd, argCp, argClass);
//builder.redirectErrorStream(true); //builder.redirectErrorStream(true);
@@ -107,12 +109,15 @@ public class ForkUtil {
return startCacheServer("org.springframework.data.gemfire.fork.CacheServerProcess"); return startCacheServer("org.springframework.data.gemfire.fork.CacheServerProcess");
} }
private static OutputStream startCacheServer(String className) { public static OutputStream startCacheServer(String args) {
String className = args.split(" ")[0];
System.out.println("main class:" + className);
if (controlFileExists(className)) { if (controlFileExists(className)) {
deleteControlFile(className); deleteControlFile(className);
} }
OutputStream os = cloneJVM(className); OutputStream os = cloneJVM(args);
int maxTime = 30000; int maxTime = 30000;
int time = 0; int time = 0;
while (!controlFileExists(className) && time < maxTime) { while (!controlFileExists(className) && time < maxTime) {

View File

@@ -18,7 +18,6 @@ package org.springframework.data.gemfire;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.springframework.context.support.GenericApplicationContext;
import org.springframework.context.support.GenericXmlApplicationContext; import org.springframework.context.support.GenericXmlApplicationContext;
/** /**

View File

@@ -20,6 +20,7 @@ import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import java.net.InetSocketAddress;
import java.util.Collection; import java.util.Collection;
import java.util.Iterator; import java.util.Iterator;
@@ -28,7 +29,6 @@ import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext; import org.springframework.context.ApplicationContext;
import org.springframework.data.gemfire.TestUtils; import org.springframework.data.gemfire.TestUtils;
import org.springframework.data.gemfire.client.PoolConnection;
import org.springframework.data.gemfire.client.PoolFactoryBean; import org.springframework.data.gemfire.client.PoolFactoryBean;
import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
@@ -41,7 +41,7 @@ import com.gemstone.gemfire.cache.client.PoolManager;
@RunWith(SpringJUnit4ClassRunner.class) @RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration("pool-ns.xml") @ContextConfiguration("pool-ns.xml")
public class PoolNamespaceTest { public class PoolNamespaceTest {
@Autowired @Autowired
private ApplicationContext context; private ApplicationContext context;
@@ -58,10 +58,10 @@ public class PoolNamespaceTest {
assertEquals(context.getBean("gemfirePool"), PoolManager.find("gemfirePool")); assertEquals(context.getBean("gemfirePool"), PoolManager.find("gemfirePool"));
PoolFactoryBean pfb = (PoolFactoryBean) context.getBean("&gemfirePool"); PoolFactoryBean pfb = (PoolFactoryBean) context.getBean("&gemfirePool");
Collection<PoolConnection> locators = TestUtils.readField("locators", pfb); Collection<InetSocketAddress> locators = TestUtils.readField("locators", pfb);
assertEquals(1, locators.size()); assertEquals(1, locators.size());
PoolConnection locator = locators.iterator().next(); InetSocketAddress locator = locators.iterator().next();
assertEquals("localhost", locator.getHost()); assertEquals("localhost", locator.getHostName());
assertEquals(40403, locator.getPort()); assertEquals(40403, locator.getPort());
} }
@@ -75,15 +75,15 @@ public class PoolNamespaceTest {
assertFalse((Boolean) TestUtils.readField("multiUserAuthentication", pfb)); assertFalse((Boolean) TestUtils.readField("multiUserAuthentication", pfb));
assertTrue((Boolean) TestUtils.readField("prSingleHopEnabled", pfb)); assertTrue((Boolean) TestUtils.readField("prSingleHopEnabled", pfb));
Collection<PoolConnection> servers = TestUtils.readField("servers", pfb); Collection<InetSocketAddress> servers = TestUtils.readField("servers", pfb);
assertEquals(2, servers.size()); assertEquals(2, servers.size());
Iterator<PoolConnection> iterator = servers.iterator(); Iterator<InetSocketAddress> iterator = servers.iterator();
PoolConnection server = iterator.next(); InetSocketAddress server = iterator.next();
assertEquals("localhost", server.getHost()); assertEquals("localhost", server.getHostName());
assertEquals(40404, server.getPort()); assertEquals(40404, server.getPort());
server = iterator.next(); server = iterator.next();
assertEquals("localhost", server.getHost()); assertEquals("localhost", server.getHostName());
assertEquals(40405, server.getPort()); assertEquals(40405, server.getPort());
} }
} }

View File

@@ -28,6 +28,7 @@ import com.gemstone.gemfire.cache.Cache;
import com.gemstone.gemfire.cache.CacheFactory; import com.gemstone.gemfire.cache.CacheFactory;
import com.gemstone.gemfire.cache.DataPolicy; import com.gemstone.gemfire.cache.DataPolicy;
import com.gemstone.gemfire.cache.Region; import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionFactory;
import com.gemstone.gemfire.cache.Scope; import com.gemstone.gemfire.cache.Scope;
import com.gemstone.gemfire.cache.server.CacheServer; import com.gemstone.gemfire.cache.server.CacheServer;
import com.gemstone.gemfire.distributed.DistributedSystem; import com.gemstone.gemfire.distributed.DistributedSystem;
@@ -43,21 +44,19 @@ public class CacheServerProcess {
props.setProperty("name", "CqServer"); props.setProperty("name", "CqServer");
props.setProperty("log-level", "warning"); props.setProperty("log-level", "warning");
System.out.println("\nConnecting to the distributed system and creating the cache."); Cache cache = new CacheFactory(props).create();
DistributedSystem ds = DistributedSystem.connect(props);
Cache cache = CacheFactory.create(ds);
// Create region. // Create region.
AttributesFactory factory = new AttributesFactory(); // Create region.
RegionFactory<Object,Object> factory = cache.createRegionFactory();
factory.setDataPolicy(DataPolicy.REPLICATE); factory.setDataPolicy(DataPolicy.REPLICATE);
factory.setScope(Scope.DISTRIBUTED_ACK); factory.setScope(Scope.DISTRIBUTED_ACK);
Region testRegion = cache.createRegion("test-cq", factory.create()); Region testRegion = factory.create("test-cq");
System.out.println("Test region, " + testRegion.getFullPath() + ", created in cache."); System.out.println("Test region, " + testRegion.getFullPath() + ", created in cache.");
// Start Cache Server. // Start Cache Server.
CacheServer server = cache.addCacheServer(); CacheServer server = cache.addCacheServer();
server.setPort(40404); server.setPort(40404);
server.setNotifyBySubscription(true);
server.start(); server.start();
ForkUtil.createControlFile(CacheServerProcess.class.getName()); ForkUtil.createControlFile(CacheServerProcess.class.getName());

Some files were not shown because too many files have changed in this diff Show More