SGF-67 - In progress
This commit is contained in:
@@ -31,6 +31,7 @@ import org.springframework.beans.factory.BeanNameAware;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.beans.factory.FactoryBean;
|
||||
import org.springframework.beans.factory.InitializingBean;
|
||||
import org.springframework.beans.factory.config.BeanPostProcessor;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.dao.DataAccessException;
|
||||
import org.springframework.dao.support.PersistenceExceptionTranslator;
|
||||
@@ -75,12 +76,14 @@ import com.gemstone.gemfire.pdx.PdxSerializer;
|
||||
* @author David Turanski
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
|
||||
|
||||
private class PdxOptions implements Runnable {
|
||||
|
||||
private final CacheFactory factory;
|
||||
@@ -277,10 +280,11 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
|
||||
factoryLocator.afterPropertiesSet();
|
||||
}
|
||||
Properties cfgProps = mergeProperties();
|
||||
|
||||
|
||||
// use the bean class loader to load Declarable classes
|
||||
Thread th = Thread.currentThread();
|
||||
ClassLoader oldTCCL = th.getContextClassLoader();
|
||||
|
||||
|
||||
try {
|
||||
th.setContextClassLoader(beanClassLoader);
|
||||
@@ -329,6 +333,7 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
|
||||
log.debug("Initialized cache from " + cacheXml);
|
||||
}
|
||||
}
|
||||
|
||||
setHeapPercentages();
|
||||
registerTransactionListeners();
|
||||
registerTransactionWriter();
|
||||
@@ -680,4 +685,7 @@ public class CacheFactoryBean implements BeanNameAware, BeanFactoryAware, BeanCl
|
||||
public void setJndiDataSources(List<JndiDataSource> jndiDataSources) {
|
||||
this.jndiDataSources = jndiDataSources;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -40,6 +40,5 @@ public interface GemfireCallback<T> {
|
||||
* @param region GemFire Region
|
||||
* @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;
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.gemstone.gemfire.CancelException;
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class GemfireCancellationException extends InvalidDataAccessResourceUsageException {
|
||||
|
||||
public GemfireCancellationException(CancelException ex) {
|
||||
|
||||
@@ -29,6 +29,7 @@ import com.gemstone.gemfire.cache.query.IndexNameConflictException;
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class GemfireIndexException extends DataIntegrityViolationException {
|
||||
|
||||
public GemfireIndexException(IndexCreationException ex) {
|
||||
|
||||
@@ -28,6 +28,7 @@ import com.gemstone.gemfire.cache.query.QueryInvalidException;
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class GemfireQueryException extends InvalidDataAccessResourceUsageException {
|
||||
|
||||
public GemfireQueryException(String message, QueryException ex) {
|
||||
|
||||
@@ -26,6 +26,7 @@ import com.gemstone.gemfire.GemFireException;
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class GemfireSystemException extends UncategorizedDataAccessException {
|
||||
|
||||
public GemfireSystemException(GemFireCheckedException ex) {
|
||||
|
||||
@@ -98,8 +98,7 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
|
||||
public boolean containsKey(final Object key) {
|
||||
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);
|
||||
}
|
||||
});
|
||||
@@ -107,8 +106,7 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
|
||||
public boolean containsKeyOnServer(final Object key) {
|
||||
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);
|
||||
}
|
||||
});
|
||||
@@ -116,8 +114,7 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
|
||||
public boolean containsValue(final Object value) {
|
||||
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);
|
||||
}
|
||||
});
|
||||
@@ -125,8 +122,7 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
|
||||
public boolean containsValueForKey(final Object key) {
|
||||
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);
|
||||
}
|
||||
});
|
||||
@@ -134,7 +130,7 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
|
||||
public <K, V> void create(final K key, final V value) {
|
||||
execute(new GemfireCallback<Object>() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public Object doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
|
||||
region.create(key, value);
|
||||
return null;
|
||||
@@ -144,7 +140,7 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
|
||||
public <K, V> V get(final K key) {
|
||||
return execute(new GemfireCallback<V>() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public V doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
|
||||
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) {
|
||||
return execute(new GemfireCallback<V>() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public V doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
|
||||
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) {
|
||||
return execute(new GemfireCallback<V>() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public V doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
|
||||
return (V) region.putIfAbsent(key, value);
|
||||
}
|
||||
@@ -171,7 +167,7 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
|
||||
public <K, V> V remove(final K key) {
|
||||
return execute(new GemfireCallback<V>() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public V doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
|
||||
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) {
|
||||
return execute(new GemfireCallback<V>() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public V doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
|
||||
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) {
|
||||
return execute(new GemfireCallback<Boolean>() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public Boolean doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
|
||||
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) {
|
||||
return execute(new GemfireCallback<Map<K, V>>() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public Map<K, V> doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
|
||||
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) {
|
||||
execute(new GemfireCallback<Object>() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public Object doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
|
||||
region.putAll(map);
|
||||
return null;
|
||||
@@ -228,7 +224,7 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
*/
|
||||
public <E> SelectResults<E> query(final String query) {
|
||||
return execute(new GemfireCallback<SelectResults<E>>() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public SelectResults<E> doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
|
||||
return region.query(query);
|
||||
}
|
||||
@@ -255,7 +251,7 @@ public class GemfireTemplate extends GemfireAccessor {
|
||||
public <E> SelectResults<E> find(final String query, final Object... params)
|
||||
throws InvalidDataAccessApiUsageException {
|
||||
return execute(new GemfireCallback<SelectResults<E>>() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public SelectResults<E> doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
|
||||
QueryService queryService = lookupQueryService(region);
|
||||
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 {
|
||||
return execute(new GemfireCallback<T>() {
|
||||
@SuppressWarnings("unchecked")
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
public T doInGemfire(Region region) throws GemFireCheckedException, GemFireException {
|
||||
QueryService queryService = lookupQueryService(region);
|
||||
Query q = queryService.newQuery(query);
|
||||
|
||||
@@ -23,6 +23,7 @@ import org.springframework.transaction.TransactionException;
|
||||
*
|
||||
* @author Costin Leau
|
||||
*/
|
||||
@SuppressWarnings("serial")
|
||||
public class GemfireTransactionCommitException extends TransactionException {
|
||||
|
||||
public GemfireTransactionCommitException(String message, Throwable cause) {
|
||||
|
||||
@@ -64,6 +64,7 @@ import com.gemstone.gemfire.cache.Region;
|
||||
*/
|
||||
// TODO add lenient behavior if a transaction is already started on the current
|
||||
// thread (what should happen then)
|
||||
@SuppressWarnings("serial")
|
||||
public class GemfireTransactionManager extends AbstractPlatformTransactionManager implements InitializingBean,
|
||||
ResourceTransactionManager {
|
||||
|
||||
@@ -218,7 +219,7 @@ public class GemfireTransactionManager extends AbstractPlatformTransactionManage
|
||||
*/
|
||||
public <K, V> void setRegion(Region<K, V> region) {
|
||||
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;
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
public boolean isRollbackOnly() {
|
||||
return rollbackOnly;
|
||||
}
|
||||
|
||||
@@ -28,8 +28,13 @@ import com.gemstone.gemfire.cache.RegionService;
|
||||
import com.gemstone.gemfire.cache.client.Pool;
|
||||
import com.gemstone.gemfire.cache.client.PoolManager;
|
||||
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.QueryService;
|
||||
import com.gemstone.gemfire.cache.query.RegionNotFoundException;
|
||||
import com.springsource.vfabric.licensing.log.Logger;
|
||||
|
||||
/**
|
||||
* Factory bean for easy declarative creation of GemFire Indexes.
|
||||
@@ -71,7 +76,7 @@ public class IndexFactoryBean implements InitializingBean, BeanNameAware, Factor
|
||||
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();
|
||||
|
||||
Index old = null;
|
||||
@@ -95,13 +100,17 @@ public class IndexFactoryBean implements InitializingBean, BeanNameAware, Factor
|
||||
}
|
||||
|
||||
Index index = null;
|
||||
|
||||
try {
|
||||
if (StringUtils.hasText(imports)) {
|
||||
index = queryService.createIndex(indexName, type, expression, from, imports);
|
||||
}
|
||||
else {
|
||||
index = queryService.createIndex(indexName, type, expression, from);
|
||||
}
|
||||
|
||||
} catch (IndexExistsException e) {
|
||||
// This is ok
|
||||
}
|
||||
|
||||
return index;
|
||||
}
|
||||
|
||||
@@ -21,13 +21,14 @@ import java.lang.reflect.Field;
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.springframework.beans.factory.DisposableBean;
|
||||
import org.springframework.context.SmartLifecycle;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.data.gemfire.client.ClientRegionFactoryBean;
|
||||
import org.springframework.data.gemfire.wan.SmartLifecycleGatewaySender;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
|
||||
import com.gemstone.gemfire.cache.asyncqueue.AsyncEventQueue;
|
||||
import com.gemstone.gemfire.cache.AttributesFactory;
|
||||
import com.gemstone.gemfire.cache.Cache;
|
||||
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.RegionFactory;
|
||||
import com.gemstone.gemfire.cache.Scope;
|
||||
import com.gemstone.gemfire.cache.asyncqueue.AsyncEventQueue;
|
||||
import com.gemstone.gemfire.cache.wan.GatewaySender;
|
||||
|
||||
/**
|
||||
@@ -55,7 +57,11 @@ import com.gemstone.gemfire.cache.wan.GatewaySender;
|
||||
* @author Costin Leau
|
||||
* @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());
|
||||
|
||||
@@ -150,13 +156,13 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
|
||||
if (cacheWriter != null) {
|
||||
regionFactory.setCacheWriter(cacheWriter);
|
||||
}
|
||||
|
||||
|
||||
if (diskStoreName != null) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
resolveDataPolicy(regionFactory, persistent, dataPolicy);
|
||||
|
||||
if (scope != null) {
|
||||
@@ -194,8 +200,7 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
|
||||
if (dataPolicy == null) {
|
||||
if (isPersistent()) {
|
||||
regionFactory.setDataPolicy(DataPolicy.PERSISTENT_REPLICATE);
|
||||
}
|
||||
else {
|
||||
} else {
|
||||
regionFactory.setDataPolicy(DataPolicy.DEFAULT);
|
||||
}
|
||||
return;
|
||||
@@ -238,23 +243,21 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
|
||||
* @param region
|
||||
*/
|
||||
protected void postProcess(Region<K, V> region) {
|
||||
// do nothing
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
if (region != null) {
|
||||
if (close) {
|
||||
if (!region.getCache().isClosed()) {
|
||||
if (!region.getRegionService().isClosed()) {
|
||||
try {
|
||||
region.close();
|
||||
}
|
||||
catch (CacheClosedException cce) {
|
||||
} catch (CacheClosedException cce) {
|
||||
// nothing to see folks, move on.
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (destroy) {
|
||||
} else if (destroy) {
|
||||
region.destroyRegion();
|
||||
}
|
||||
}
|
||||
@@ -414,4 +417,73 @@ public class RegionFactoryBean<K, V> extends RegionLookupFactoryBean<K, V> imple
|
||||
protected boolean isNotPersistent() {
|
||||
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();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.springframework.data.gemfire.client;
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import java.util.logging.Handler;
|
||||
|
||||
import org.springframework.beans.factory.BeanInitializationException;
|
||||
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.StringUtils;
|
||||
|
||||
import com.gemstone.gemfire.LogWriter;
|
||||
import com.gemstone.gemfire.cache.GemFireCache;
|
||||
import com.gemstone.gemfire.cache.client.ClientCacheFactory;
|
||||
import com.gemstone.gemfire.cache.client.Pool;
|
||||
import com.gemstone.gemfire.cache.client.PoolManager;
|
||||
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;
|
||||
|
||||
/**
|
||||
@@ -103,16 +108,15 @@ public class ClientCacheFactoryBean extends CacheFactoryBean {
|
||||
if (StringUtils.hasText(poolName)) {
|
||||
p = PoolManager.find(poolName);
|
||||
}
|
||||
// initialize a client-like Distributed System before initializing
|
||||
// the pool
|
||||
// Bind this client cache to a pool that hasn't been created yet.
|
||||
|
||||
// initialize a client-like Distributed System before initializing
|
||||
// the pool
|
||||
|
||||
if (p == null) {
|
||||
Properties prop = mergeProperties();
|
||||
prop.setProperty("mcast-port", "0");
|
||||
prop.setProperty("locators", "");
|
||||
|
||||
DistributedSystem system = DistributedSystem.connect(prop);
|
||||
PoolFactoryBean.connectToTemporaryDs();
|
||||
}
|
||||
|
||||
|
||||
if (StringUtils.hasText(poolName)) {
|
||||
try {
|
||||
|
||||
@@ -134,6 +138,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean {
|
||||
p = getBeanFactory().getBean(Pool.class);
|
||||
this.poolName = p.getName();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (p != null) {
|
||||
@@ -167,7 +172,7 @@ public class ClientCacheFactoryBean extends CacheFactoryBean {
|
||||
}
|
||||
|
||||
List<InetSocketAddress> servers = p.getServers();
|
||||
if (locators != null) {
|
||||
if (servers != null) {
|
||||
for (InetSocketAddress inet : servers) {
|
||||
ccf.addPoolServer(inet.getHostName(), inet.getPort());
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
package org.springframework.data.gemfire.client;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
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.PoolFactory;
|
||||
import com.gemstone.gemfire.cache.client.PoolManager;
|
||||
import com.gemstone.gemfire.distributed.DistributedSystem;
|
||||
import com.gemstone.gemfire.distributed.internal.InternalDistributedSystem;
|
||||
import java.net.InetSocketAddress;
|
||||
|
||||
/**
|
||||
* 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
|
||||
private String beanName;
|
||||
private String name;
|
||||
private Collection<PoolConnection> locators;
|
||||
private Collection<PoolConnection> servers;
|
||||
private Collection<InetSocketAddress> locators;
|
||||
private Collection<InetSocketAddress> servers;
|
||||
|
||||
private BeanFactory beanFactory;
|
||||
|
||||
@@ -109,8 +112,8 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean,
|
||||
|
||||
// eagerly initialize cache (if needed)
|
||||
if (InternalDistributedSystem.getAnyInstance() == null) {
|
||||
// no cache found, do eager initialization
|
||||
beanFactory.getBean(GemFireCache.class);
|
||||
// no cache found, create a temp connection
|
||||
connectToTemporaryDs();
|
||||
}
|
||||
|
||||
// first check the configured pools
|
||||
@@ -137,15 +140,15 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean,
|
||||
PoolFactory poolFactory = PoolManager.createFactory();
|
||||
|
||||
if (!CollectionUtils.isEmpty(locators)) {
|
||||
for (PoolConnection connection : locators) {
|
||||
poolFactory.addLocator(connection.getHost(),
|
||||
for (InetSocketAddress connection : locators) {
|
||||
poolFactory.addLocator(connection.getHostName(),
|
||||
connection.getPort());
|
||||
}
|
||||
}
|
||||
|
||||
if (!CollectionUtils.isEmpty(servers)) {
|
||||
for (PoolConnection connection : servers) {
|
||||
poolFactory.addServer(connection.getHost(),
|
||||
for (InetSocketAddress connection : servers) {
|
||||
poolFactory.addServer(connection.getHostName(),
|
||||
connection.getPort());
|
||||
}
|
||||
}
|
||||
@@ -209,7 +212,7 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean,
|
||||
* @param locators
|
||||
* the locators to set
|
||||
*/
|
||||
public void setLocators(Collection<PoolConnection> locators) {
|
||||
public void setLocators(Collection<InetSocketAddress> locators) {
|
||||
this.locators = locators;
|
||||
}
|
||||
|
||||
@@ -217,7 +220,7 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean,
|
||||
* @param servers
|
||||
* the servers to set
|
||||
*/
|
||||
public void setServers(Collection<PoolConnection> servers) {
|
||||
public void setServers(Collection<InetSocketAddress> servers) {
|
||||
this.servers = servers;
|
||||
}
|
||||
|
||||
@@ -377,4 +380,16 @@ public class PoolFactoryBean implements FactoryBean<Pool>, InitializingBean,
|
||||
public void setPrSingleHopEnabled(boolean 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);
|
||||
}
|
||||
}
|
||||
@@ -19,11 +19,10 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.data.gemfire.wan.AsyncEventQueueFactoryBean;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
import org.w3c.dom.Element;
|
||||
|
||||
import com.gemstone.gemfire.internal.lang.StringUtils;
|
||||
|
||||
/**
|
||||
* @author David Turanski
|
||||
*
|
||||
@@ -41,8 +40,10 @@ public class AsyncEventQueueParser extends AbstractSingleBeanDefinitionParser {
|
||||
Element asyncEventListenerElement = DomUtils.getChildElementByTagName(element, "async-event-listener");
|
||||
Object asyncEventListener = ParsingUtils.parseRefOrSingleNestedBeanDeclaration(parserContext,
|
||||
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.addConstructorArgValue(asyncEventListener);
|
||||
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, "persistent");
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package org.springframework.data.gemfire.config;
|
||||
import java.util.List;
|
||||
|
||||
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.BeanDefinitionBuilder;
|
||||
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.ParserContext;
|
||||
import org.springframework.data.gemfire.CacheFactoryBean;
|
||||
import org.springframework.data.gemfire.GemfireBeanPostProcessor;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
@@ -52,6 +54,9 @@ class CacheParser extends AbstractSimpleBeanDefinitionParser {
|
||||
@Override
|
||||
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder 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.setPropertyReference(element, builder, "properties-ref", "properties");
|
||||
|
||||
@@ -37,7 +37,7 @@ class ClientCacheParser extends CacheParser {
|
||||
@Override
|
||||
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder 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
|
||||
|
||||
@@ -36,10 +36,12 @@ class GatewaySenderParser extends AbstractSimpleBeanDefinitionParser {
|
||||
|
||||
@Override
|
||||
protected void doParse(Element element, ParserContext parserContext, BeanDefinitionBuilder builder) {
|
||||
builder.setLazyInit(false);
|
||||
|
||||
String cacheRef = element.getAttribute("cache-ref");
|
||||
|
||||
// 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, "batch-size");
|
||||
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, "persistent");
|
||||
ParsingUtils.setPropertyValue(element, builder, "parallel");
|
||||
ParsingUtils.setPropertyValue(element, builder, NAME_ATTRIBUTE);
|
||||
|
||||
Element eventFilterElement = DomUtils.getChildElementByTagName(element, "event-filter");
|
||||
if (eventFilterElement != null) {
|
||||
@@ -63,5 +66,25 @@ class GatewaySenderParser extends AbstractSimpleBeanDefinitionParser {
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
|
||||
package org.springframework.data.gemfire.config;
|
||||
|
||||
import java.net.InetSocketAddress;
|
||||
import java.util.List;
|
||||
|
||||
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.xml.AbstractSimpleBeanDefinitionParser;
|
||||
import org.springframework.beans.factory.xml.ParserContext;
|
||||
import org.springframework.data.gemfire.client.PoolConnection;
|
||||
import org.springframework.data.gemfire.client.PoolFactoryBean;
|
||||
import org.springframework.util.StringUtils;
|
||||
import org.springframework.util.xml.DomUtils;
|
||||
@@ -35,13 +35,16 @@ import org.w3c.dom.Element;
|
||||
* Parser for <pool;gt; definitions.
|
||||
*
|
||||
* @author Costin Leau
|
||||
* @author David Turanski
|
||||
*/
|
||||
class PoolParser extends AbstractSimpleBeanDefinitionParser {
|
||||
|
||||
@Override
|
||||
protected Class<?> getBeanClass(Element element) {
|
||||
return PoolFactoryBean.class;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void postProcess(BeanDefinitionBuilder builder, Element element) {
|
||||
List<Element> subElements = DomUtils.getChildElements(element);
|
||||
ManagedList<Object> locators = new ManagedList<Object>(subElements.size());
|
||||
@@ -77,9 +80,9 @@ class PoolParser extends AbstractSimpleBeanDefinitionParser {
|
||||
}
|
||||
|
||||
private BeanDefinition parseConnection(Element element) {
|
||||
BeanDefinitionBuilder defBuilder = BeanDefinitionBuilder.genericBeanDefinition(PoolConnection.class);
|
||||
ParsingUtils.setPropertyValue(element, defBuilder, "host", "host");
|
||||
ParsingUtils.setPropertyValue(element, defBuilder, "port", "port");
|
||||
BeanDefinitionBuilder defBuilder = BeanDefinitionBuilder.genericBeanDefinition(InetSocketAddress.class);
|
||||
defBuilder.addConstructorArgValue(element.getAttribute("host"));
|
||||
defBuilder.addConstructorArgValue(element.getAttribute("port"));
|
||||
return defBuilder.getBeanDefinition();
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -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());
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -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
|
||||
* the License. You may obtain a copy of the License at
|
||||
|
||||
@@ -12,11 +12,10 @@
|
||||
*/
|
||||
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.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
@@ -25,23 +24,21 @@ import org.springframework.util.ObjectUtils;
|
||||
import org.springframework.util.ReflectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
import com.gemstone.gemfire.cache.execute.Function;
|
||||
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.partition.PartitionRegionHelper;
|
||||
import com.gemstone.gemfire.internal.util.ArrayUtils;
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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)
|
||||
* @author David Turanski
|
||||
*
|
||||
*/
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
public class PojoFunctionWrapper implements Function {
|
||||
|
||||
@@ -53,9 +50,13 @@ public class PojoFunctionWrapper implements Function {
|
||||
private final Object target;
|
||||
private final Method method;
|
||||
private final String id;
|
||||
private volatile Integer regionParameterPosition;
|
||||
|
||||
private final FunctionArgumentResolver functionArgumentResolver;
|
||||
|
||||
public PojoFunctionWrapper(Object target, Method method, String id) {
|
||||
|
||||
this.functionArgumentResolver = new FunctionContextInjectingArgumentResolver(method);
|
||||
|
||||
this.id = StringUtils.hasText(id) ? id : ClassUtils.getQualifiedMethodName(method);
|
||||
this.target = target;
|
||||
this.method = method;
|
||||
@@ -95,31 +96,13 @@ public class PojoFunctionWrapper implements Function {
|
||||
this.optimizeForWrite = optimizeForWrite;
|
||||
}
|
||||
|
||||
public void setRegionParameterPosition(int regionParameterPosition) {
|
||||
this.regionParameterPosition = regionParameterPosition;
|
||||
}
|
||||
|
||||
//@Override
|
||||
public void execute(FunctionContext functionContext) {
|
||||
|
||||
Object[] args = this.functionArgumentResolver.resolveFunctionArguments(functionContext);
|
||||
|
||||
Object[] args = (functionContext.getArguments().getClass().isArray()) ? (Object[]) functionContext
|
||||
.getArguments() : new Object[] { functionContext.getArguments() };
|
||||
|
||||
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 {
|
||||
|
||||
}
|
||||
|
||||
Object result = null;
|
||||
|
||||
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()) {
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
* @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;
|
||||
return (Object) ReflectionUtils.invokeMethod(method, target, (Object[]) args);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private void sendResults(ResultSender<Object> resultSender, Serializable result) {
|
||||
private void sendResults(ResultSender<Object> resultSender, Object result) {
|
||||
if (result == null) {
|
||||
resultSender.lastResult(null);
|
||||
return;
|
||||
}
|
||||
|
||||
Serializable lastItem = result;
|
||||
|
||||
List<Serializable> results = null;
|
||||
|
||||
List<Object> results = null;
|
||||
|
||||
if (ObjectUtils.isArray(result)) {
|
||||
results = Arrays.asList((Serializable[]) result);
|
||||
results = Arrays.asList((Object[]) result);
|
||||
|
||||
} else if (List.class.isAssignableFrom(result.getClass())) {
|
||||
results = (List<Serializable>) result;
|
||||
results = (List<Object>) result;
|
||||
}
|
||||
|
||||
if (results != null) {
|
||||
int i = 0;
|
||||
for (Serializable item : results) {
|
||||
for (Object item : results) {
|
||||
if (i++ < results.size() - 1) {
|
||||
resultSender.sendResult(item);
|
||||
} else {
|
||||
lastItem = item;
|
||||
resultSender.lastResult(item);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
resultSender.lastResult(result);
|
||||
}
|
||||
resultSender.lastResult(lastItem);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
* the License. You may obtain a copy of the License at
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 {};
|
||||
}
|
||||
@@ -19,9 +19,14 @@ 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 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
|
||||
*
|
||||
*/
|
||||
@@ -29,36 +34,6 @@ import org.springframework.context.annotation.ComponentScan.Filter;
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Documented
|
||||
@Inherited
|
||||
@Import(GemfireFunctionPostBeanProcessorRegistrar.class)
|
||||
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 {};
|
||||
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -18,6 +18,9 @@ import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
*
|
||||
* Used to declare a concrete method as a GemFire function implementation
|
||||
*
|
||||
* @author David Turanski
|
||||
*
|
||||
*/
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
*/
|
||||
package org.springframework.data.gemfire.function.config;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.Map;
|
||||
@@ -24,13 +23,16 @@ import org.springframework.util.Assert;
|
||||
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
|
||||
*
|
||||
*/
|
||||
public class GemfireFunctionBeanPostProcessor implements BeanPostProcessor {
|
||||
|
||||
private static final String GEMFIRE_FUNCTION_ANNOTATION_NAME = GemfireFunction.class.getName();
|
||||
private static final String REGION_DATA_ANNOTATION_NAME = RegionData.class.getName();
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String)
|
||||
@@ -45,7 +47,14 @@ public class GemfireFunctionBeanPostProcessor implements BeanPostProcessor {
|
||||
*/
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
|
||||
|
||||
|
||||
registerAnyDeclaredGemfireFunctionMethods(bean);
|
||||
|
||||
return bean;
|
||||
}
|
||||
|
||||
private void registerAnyDeclaredGemfireFunctionMethods (Object bean) {
|
||||
|
||||
Method[] methods = ReflectionUtils.getAllDeclaredMethods(bean.getClass());
|
||||
|
||||
for (Method method: methods) {
|
||||
@@ -53,34 +62,9 @@ public class GemfireFunctionBeanPostProcessor implements BeanPostProcessor {
|
||||
if (annotation != null) {
|
||||
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);
|
||||
|
||||
processParameterAnnotations(method);
|
||||
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -12,35 +12,49 @@
|
||||
*/
|
||||
package org.springframework.data.gemfire.function.config;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
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;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author David Turanski
|
||||
*
|
||||
*/
|
||||
public abstract class GemfireFunctionUtils {
|
||||
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") : "";
|
||||
|
||||
PojoFunctionWrapper function = new PojoFunctionWrapper(target,method, id);
|
||||
|
||||
|
||||
/**
|
||||
* Wrap a target object and method in a GemFire Function and register the function to the {@link FunctionService}
|
||||
*
|
||||
* @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")) {
|
||||
function.setHA((Boolean)attributes.get("HA"));
|
||||
}
|
||||
if (attributes.containsKey("optimizeForWrite")) {
|
||||
function.setOptimizeForWrite((Boolean)attributes.get("optimizeForWrite"));
|
||||
}
|
||||
|
||||
function.setHA((Boolean) attributes.get("HA"));
|
||||
}
|
||||
if (attributes.containsKey("optimizeForWrite")) {
|
||||
function.setOptimizeForWrite((Boolean) attributes.get("optimizeForWrite"));
|
||||
}
|
||||
|
||||
if (FunctionService.isRegistered(function.getId())) {
|
||||
if (overwrite) {
|
||||
if (log.isDebugEnabled()) {
|
||||
@@ -49,7 +63,7 @@ public abstract class GemfireFunctionUtils {
|
||||
FunctionService.unregisterFunction(function.getId());
|
||||
}
|
||||
}
|
||||
if (!FunctionService.isRegistered(function.getId())){
|
||||
if (!FunctionService.isRegistered(function.getId())) {
|
||||
FunctionService.registerFunction(function);
|
||||
if (log.isDebugEnabled()) {
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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 "";
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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 "";
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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 "";
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -23,11 +23,11 @@ import java.lang.annotation.Target;
|
||||
* {@link Map}. The contents depends on the region configuration (for a partitioned region, this will
|
||||
* contain only entries for the local partition)
|
||||
* and any filters configured for the function context.
|
||||
*
|
||||
* @author David Turanski
|
||||
*
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.PARAMETER})
|
||||
public @interface RegionData {
|
||||
String value() default "";
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
@@ -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 AllMembersFunctionExecution extends FunctionExecution {
|
||||
|
||||
@Override
|
||||
protected Execution getExecution() {
|
||||
return FunctionService.onMembers();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
* 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
|
||||
* 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.Function;
|
||||
import com.gemstone.gemfire.cache.execute.FunctionService;
|
||||
import com.gemstone.gemfire.distributed.DistributedSystem;
|
||||
import com.gemstone.gemfire.distributed.DistributedMember;
|
||||
|
||||
/**
|
||||
* @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) {
|
||||
super(function, args);
|
||||
this.distributedSystem = distributedSystem;
|
||||
public DistributedMemberFunctionExecution(DistributedMember distributedMember) {
|
||||
super();
|
||||
Assert.notNull(distributedMember);
|
||||
this.distributedMember = distributedMember;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.gemfire.function.FunctionExecution#getExecution()
|
||||
*/
|
||||
|
||||
@Override
|
||||
protected Execution getExecution() {
|
||||
return FunctionService.onMembers(this.distributedSystem);
|
||||
return FunctionService.onMember(this.distributedMember);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
* 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
|
||||
* 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.List;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
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.Function;
|
||||
import com.gemstone.gemfire.cache.execute.FunctionException;
|
||||
import com.gemstone.gemfire.cache.execute.FunctionService;
|
||||
import com.gemstone.gemfire.cache.execute.ResultCollector;
|
||||
|
||||
/**
|
||||
* Base class for * Creating a GemFire {@link Execution} using {@link FunctionService}
|
||||
* @author David Turanski
|
||||
*/
|
||||
|
||||
public abstract class FunctionExecution<T> {
|
||||
public abstract class FunctionExecution {
|
||||
protected final Log logger = LogFactory.getLog(this.getClass());
|
||||
|
||||
private volatile ResultCollector<?, ?> collector;
|
||||
private final Serializable[] args;
|
||||
private Object[] args;
|
||||
private Function function;
|
||||
private final String functionId;
|
||||
private String functionId;
|
||||
private long timeout;
|
||||
|
||||
public FunctionExecution(Function function, Serializable... args) {
|
||||
public FunctionExecution(Function function, Object... args) {
|
||||
Assert.notNull(function,"function cannot be null");
|
||||
this.function = function;
|
||||
this.functionId = function.getId();
|
||||
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");
|
||||
this.functionId = functionId;
|
||||
this.args = args;
|
||||
}
|
||||
|
||||
protected FunctionExecution() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
public ResultCollector<?, ?> getCollector() {
|
||||
return collector;
|
||||
}
|
||||
|
||||
public Serializable[] getArgs() {
|
||||
public Object[] getArgs() {
|
||||
return args;
|
||||
}
|
||||
|
||||
@@ -74,9 +81,10 @@ public abstract class FunctionExecution<T> {
|
||||
this.collector = collector;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<T> execute() {
|
||||
public <T> Iterable<T> execute() {
|
||||
Execution execution = this.getExecution();
|
||||
if (getKeys() != null) {
|
||||
execution = execution.withFilter(getKeys());
|
||||
@@ -96,9 +104,11 @@ public abstract class FunctionExecution<T> {
|
||||
resultsCollector = (ResultCollector<?,?>) execution.execute(function);
|
||||
}
|
||||
|
||||
Iterable<T> results = null;
|
||||
|
||||
if (this.timeout > 0 ){
|
||||
try {
|
||||
return (List<T>)resultsCollector.getResult(this.timeout, TimeUnit.MILLISECONDS);
|
||||
results= (Iterable<T>)resultsCollector.getResult(this.timeout, TimeUnit.MILLISECONDS);
|
||||
}
|
||||
catch (FunctionException e) {
|
||||
throw new RuntimeException(e);
|
||||
@@ -107,27 +117,52 @@ public abstract class FunctionExecution<T> {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
return (List<T>)resultsCollector.getResult();
|
||||
|
||||
results = (Iterable<T>) resultsCollector.getResult();
|
||||
}
|
||||
|
||||
return replaceSingletonNullCollectionWithEmptyList(results);
|
||||
|
||||
}
|
||||
|
||||
public T executeAndExtract() {
|
||||
return this.execute().get(0);
|
||||
public <T> T executeAndExtract() {
|
||||
Iterable<T> results = this.execute();
|
||||
if (results == null || !results.iterator().hasNext()) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return results.iterator().next();
|
||||
}
|
||||
|
||||
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() {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void setTimeout(long timeout) {
|
||||
public FunctionExecution setTimeout(long timeout) {
|
||||
this.timeout = timeout;
|
||||
return this;
|
||||
}
|
||||
|
||||
public long getTimeout() {
|
||||
return timeout;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return
|
||||
@@ -135,5 +170,23 @@ public abstract class FunctionExecution<T> {
|
||||
private boolean isRegisteredFunction() {
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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
|
||||
* 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
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* A callback for Gemfire Function Templates
|
||||
* @author David Turanski
|
||||
*
|
||||
*/
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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");
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -10,38 +10,35 @@
|
||||
* 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;
|
||||
package org.springframework.data.gemfire.function.execution;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.Set;
|
||||
|
||||
import org.springframework.util.CollectionUtils;
|
||||
|
||||
import com.gemstone.gemfire.cache.Region;
|
||||
import com.gemstone.gemfire.cache.execute.Execution;
|
||||
import com.gemstone.gemfire.cache.execute.Function;
|
||||
import com.gemstone.gemfire.cache.execute.FunctionService;
|
||||
|
||||
|
||||
/**
|
||||
* Creates a GemFire {@link Execution} using {code}FunctionService.onRegion(Region region){code}
|
||||
* @author David Turanski
|
||||
*
|
||||
*/
|
||||
public class RegionFunctionExecution<T> extends FunctionExecution<T> {
|
||||
public class RegionFunctionExecution extends FunctionExecution {
|
||||
|
||||
|
||||
private final Region<?, ?> region;
|
||||
private volatile Set<?> keys;
|
||||
|
||||
public RegionFunctionExecution(Region<?, ?> region, Function function, Serializable... args) {
|
||||
super(function, args);
|
||||
public RegionFunctionExecution(Region<?, ?> region) {
|
||||
super();
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
public RegionFunctionExecution(Region<?, ?> region, String functionId, Serializable... args) {
|
||||
super(functionId, args);
|
||||
this.region = region;
|
||||
}
|
||||
|
||||
public void setKeys(Set<?> keys) {
|
||||
public RegionFunctionExecution setKeys(Set<?> keys) {
|
||||
this.keys = keys;
|
||||
return this;
|
||||
}
|
||||
|
||||
protected Set<?> getKeys() {
|
||||
@@ -53,6 +50,10 @@ public class RegionFunctionExecution<T> extends FunctionExecution<T> {
|
||||
*/
|
||||
@Override
|
||||
protected Execution getExecution() {
|
||||
return FunctionService.onRegion(region);
|
||||
Execution execution = FunctionService.onRegion(region);
|
||||
if (!CollectionUtils.isEmpty(this.keys) ) {
|
||||
execution = execution.withFilter(keys);
|
||||
}
|
||||
return execution;
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
* 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
|
||||
* 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.execute.Execution;
|
||||
import com.gemstone.gemfire.cache.execute.Function;
|
||||
import com.gemstone.gemfire.cache.execute.FunctionService;
|
||||
|
||||
/**
|
||||
* Creates a GemFire {@link Execution} using {code}FunctionService.onServers(RegionService regionService){code}
|
||||
* @author David Turanski
|
||||
*
|
||||
*/
|
||||
public class ServersFunctionExecution<T> extends FunctionExecution<T> {
|
||||
public class ServersFunctionExecution extends FunctionExecution {
|
||||
|
||||
|
||||
private final RegionService regionService;
|
||||
@@ -34,25 +34,12 @@ public class ServersFunctionExecution<T> extends FunctionExecution<T> {
|
||||
* @param function
|
||||
* @param args
|
||||
*/
|
||||
public ServersFunctionExecution(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 ServersFunctionExecution(RegionService regionService, String functionId, Serializable... args) {
|
||||
super(functionId, args);
|
||||
public ServersFunctionExecution(RegionService regionService ) {
|
||||
super();
|
||||
Assert.notNull(regionService,"regionService cannot be null");
|
||||
this.regionService = regionService;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.data.gemfire.function.FunctionExecution#getExecution()
|
||||
*/
|
||||
@Override
|
||||
protected Execution getExecution() {
|
||||
return FunctionService.onServers(this.regionService);
|
||||
@@ -176,7 +176,7 @@ public class AsmInstantiatorGenerator implements InstantiatorGenerator, Opcodes
|
||||
}
|
||||
|
||||
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 });
|
||||
FieldVisitor fv = cw.visitField(ACC_PRIVATE + ACC_FINAL + ACC_STATIC, CLASS_FIELD_NAME, CLASS_DESCRIPTOR, null,
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -34,15 +34,25 @@ public abstract class AbstractWANComponentFactoryBean<T> implements FactoryBean<
|
||||
DisposableBean {
|
||||
protected Log log = LogFactory.getLog(this.getClass());
|
||||
|
||||
protected String name;
|
||||
private String name;
|
||||
|
||||
protected final Cache cache;
|
||||
|
||||
protected Object factory;
|
||||
|
||||
private String beanName;
|
||||
|
||||
protected AbstractWANComponentFactoryBean(Cache cache) {
|
||||
this.cache = cache;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name!=null ? name: beanName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() throws Exception {
|
||||
@@ -50,13 +60,13 @@ public abstract class AbstractWANComponentFactoryBean<T> implements FactoryBean<
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void setBeanName(String name) {
|
||||
this.name = name;
|
||||
public final void setBeanName(String beanName) {
|
||||
this.beanName = beanName;
|
||||
}
|
||||
|
||||
@Override
|
||||
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");
|
||||
doInit();
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ public class AsyncEventQueueFactoryBean extends AbstractWANComponentFactoryBean<
|
||||
asyncEventQueueFactory.setMaximumQueueMemory(maximumQueueMemory);
|
||||
}
|
||||
|
||||
asyncEventQueue = asyncEventQueueFactory.create(name, asyncEventListener);
|
||||
asyncEventQueue = asyncEventQueueFactory.create(getName(), asyncEventListener);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -76,6 +76,7 @@ public class GatewayHubFactoryBean extends AbstractWANComponentFactoryBean<Gatew
|
||||
|
||||
@Override
|
||||
protected void doInit() {
|
||||
String name = getName();
|
||||
gatewayHub = cache.addGatewayHub(name, port == null ? GatewayHub.DEFAULT_PORT : port);
|
||||
|
||||
if (log.isDebugEnabled()) {
|
||||
|
||||
@@ -52,8 +52,6 @@ public class GatewayReceiverFactoryBean extends AbstractWANComponentFactoryBean<
|
||||
*/
|
||||
public GatewayReceiverFactoryBean(Cache cache) {
|
||||
super(cache);
|
||||
// Bean name not required.
|
||||
this.name = "gateway-receiver";
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -33,7 +33,7 @@ import com.gemstone.gemfire.cache.wan.GatewayTransportFilter;
|
||||
* @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 GatewaySender gatewaySender;
|
||||
@@ -58,7 +58,7 @@ public class GatewaySenderFactoryBean extends AbstractWANComponentFactoryBean<Ga
|
||||
|
||||
private Integer dispatcherThreads;
|
||||
|
||||
private Boolean manualStart;
|
||||
private boolean manualStart = false;
|
||||
|
||||
private Integer maximumQueueMemory;
|
||||
|
||||
@@ -82,12 +82,12 @@ public class GatewaySenderFactoryBean extends AbstractWANComponentFactoryBean<Ga
|
||||
|
||||
@Override
|
||||
public GatewaySender getObject() throws Exception {
|
||||
return gatewaySender;
|
||||
return new SmartLifecycleGatewaySender(gatewaySender, !manualStart);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<?> getObjectType() {
|
||||
return GatewaySender.class;
|
||||
return SmartLifecycleGatewaySender.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -151,9 +151,9 @@ public class GatewaySenderFactoryBean extends AbstractWANComponentFactoryBean<Ga
|
||||
if (dispatcherThreads != null) {
|
||||
gatewaySenderFactory.setDispatcherThreads(dispatcherThreads);
|
||||
}
|
||||
if (manualStart != null) {
|
||||
gatewaySenderFactory.setManualStart(manualStart);
|
||||
}
|
||||
|
||||
gatewaySenderFactory.setManualStart(true);
|
||||
|
||||
if (maximumQueueMemory != null) {
|
||||
gatewaySenderFactory.setMaximumQueueMemory(maximumQueueMemory);
|
||||
}
|
||||
@@ -163,7 +163,7 @@ public class GatewaySenderFactoryBean extends AbstractWANComponentFactoryBean<Ga
|
||||
if (socketReadTimeout != null) {
|
||||
gatewaySenderFactory.setSocketReadTimeout(socketReadTimeout);
|
||||
}
|
||||
gatewaySender = gatewaySenderFactory.create(name, remoteDistributedSystemId);
|
||||
gatewaySender = gatewaySenderFactory.create(getName(), remoteDistributedSystemId);
|
||||
}
|
||||
|
||||
public void setRemoteDistributedSystemId(int remoteDistributedSystemId) {
|
||||
@@ -233,5 +233,4 @@ public class GatewaySenderFactoryBean extends AbstractWANComponentFactoryBean<Ga
|
||||
public void setSocketReadTimeout(Integer socketReadTimeout) {
|
||||
this.socketReadTimeout = socketReadTimeout;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user