SGF-67 - In progress

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

View File

@@ -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;
}
}

View File

@@ -0,0 +1,56 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire;
import org.springframework.beans.BeansException;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.BeanFactoryAware;
import org.springframework.beans.factory.config.BeanPostProcessor;
import org.springframework.beans.factory.support.DefaultListableBeanFactory;
/**
*
* Work around to ensure dependent disk stores are created before gateway senders
*
* @author David Turanski
*
*/
public class GemfireBeanPostProcessor implements BeanPostProcessor, BeanFactoryAware {
private DefaultListableBeanFactory beanFactory;
/* (non-Javadoc)
* @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String)
*/
@Override
public Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String)
*/
@Override
public Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
return bean;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.BeanFactoryAware#setBeanFactory(org.springframework.beans.factory.BeanFactory)
*/
@Override
public void setBeanFactory(BeanFactory beanFactory) throws BeansException {
this.beanFactory = (DefaultListableBeanFactory)beanFactory;
}
}

View File

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

View File

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

View File

@@ -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) {

View File

@@ -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) {

View File

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

View File

@@ -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);

View File

@@ -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) {

View File

@@ -64,6 +64,7 @@ import com.gemstone.gemfire.cache.Region;
*/
// TODO add lenient behavior if a transaction is already started on the current
// 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;
}

View File

@@ -28,8 +28,13 @@ import com.gemstone.gemfire.cache.RegionService;
import com.gemstone.gemfire.cache.client.Pool;
import com.gemstone.gemfire.cache.client.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;
}

View File

@@ -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();
}
}

View File

@@ -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());
}

View File

@@ -1,58 +0,0 @@
/*
* Copyright 2010-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.gemfire.client;
/**
* Simple holder class used for configuring servers or locators for GemFire pools.
*
* @see com.gemstone.gemfire.cache.client.PoolFactory
*
* @author Costin Leau
*/
public class PoolConnection {
private String host;
private int port;
/**
* @return the host
*/
public String getHost() {
return host;
}
/**
* @param host the host to set
*/
public void setHost(String host) {
this.host = host;
}
/**
* @return the port
*/
public int getPort() {
return port;
}
/**
* @param port the port to set
*/
public void setPort(int port) {
this.port = port;
}
}

View File

@@ -17,6 +17,7 @@
package org.springframework.data.gemfire.client;
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);
}
}

View File

@@ -19,11 +19,10 @@ import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSingleBeanDefinitionParser;
import org.springframework.beans.factory.xml.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);
}
}
}
}

View File

@@ -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");

View File

@@ -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

View File

@@ -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);
}
}
}
}

View File

@@ -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 &lt;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();
}

View File

@@ -0,0 +1,35 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function;
import com.gemstone.gemfire.cache.execute.FunctionContext;
/**
* @author David Turanski
*
*/
public class DefaultFunctionArgumentResolver implements FunctionArgumentResolver {
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.FunctionArgumentResolver#resolveFunctionArguments(com.gemstone.gemfire.cache.execute.FunctionContext)
*/
@Override
public Object[] resolveFunctionArguments(FunctionContext functionContext) {
Object[] args = (functionContext.getArguments().getClass().isArray()) ? (Object[]) functionContext
.getArguments() : new Object[] { functionContext.getArguments() };
return args;
}
}

View File

@@ -0,0 +1,24 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function;
import com.gemstone.gemfire.cache.execute.FunctionContext;
/**
* Strategy Interface for resolving function invocation arguments, given a {@link FunctionContext}
* @author David Turanski
*
*/
public interface FunctionArgumentResolver {
public Object[] resolveFunctionArguments(FunctionContext functionContext);
}

View File

@@ -0,0 +1,140 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function;
import java.lang.reflect.Method;
import java.util.Map;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.data.gemfire.function.config.Filter;
import org.springframework.data.gemfire.function.config.GemfireFunctionUtils;
import org.springframework.data.gemfire.function.config.RegionData;
import org.springframework.data.gemfire.util.ArrayUtils;
import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.execute.FunctionContext;
import com.gemstone.gemfire.cache.execute.RegionFunctionContext;
import com.gemstone.gemfire.cache.partition.PartitionRegionHelper;
/**
* @author David Turanski
*
*/
public class FunctionContextInjectingArgumentResolver extends DefaultFunctionArgumentResolver {
private static Log logger = LogFactory.getLog(FunctionContextInjectingArgumentResolver.class);
private final int regionParameterPosition;
private final int filterParameterPosition;
private final int functionContextParameterPosition;
private final Method method;
public FunctionContextInjectingArgumentResolver(Method method) {
this.method = method;
int annotatedRegionDataParameterPosition = GemfireFunctionUtils.getAnnotationParameterPosition(method, RegionData.class, new Class[]{Map.class});
int regionTypeParameterPosition = getArgumentTypePosition(method,Region.class);
if (annotatedRegionDataParameterPosition >=0 && regionTypeParameterPosition >= 0) {
Assert.isTrue(annotatedRegionDataParameterPosition == regionTypeParameterPosition,
String.format("Function method signature for method %s cannot contain an @RegionData parameter and a different Region type parameter", method.getName()));
}
int tempRegionParameterPosition = -1;
if (annotatedRegionDataParameterPosition >=0 ) {
tempRegionParameterPosition = annotatedRegionDataParameterPosition;
} else if (regionTypeParameterPosition >=0) {
tempRegionParameterPosition = regionTypeParameterPosition;
}
regionParameterPosition = tempRegionParameterPosition;
filterParameterPosition = GemfireFunctionUtils.getAnnotationParameterPosition(method, Filter.class, new Class[]{Set.class});
functionContextParameterPosition = getArgumentTypePosition(method,FunctionContext.class);
if (regionParameterPosition >=0 && filterParameterPosition >=0) {
Assert.state(regionParameterPosition != filterParameterPosition, "region parameter and filter parameter must be different");
}
}
@Override
public Object[] resolveFunctionArguments(FunctionContext functionContext) {
Object[] args = super.resolveFunctionArguments(functionContext);
if (functionContext instanceof RegionFunctionContext) {
if (this.regionParameterPosition >= 0) {
args = ArrayUtils.insert(args, regionParameterPosition, getRegionForContext((RegionFunctionContext)functionContext));
}
if (this.filterParameterPosition >= 0) {
args = ArrayUtils.insert(args, filterParameterPosition, ((RegionFunctionContext)functionContext).getFilter());
}
if (this.functionContextParameterPosition >= 0) {
args = ArrayUtils.insert(args, functionContextParameterPosition, functionContext);
}
}
Assert.isTrue(args.length == method.getParameterTypes().length,
String.format("wrong number of arguments for method %s. Expected :%d, actual: %d", method.getName(),
method.getParameterTypes().length, args.length));
return args;
}
/*
* @param regionFunctionContext
* @return
*/
private static Region<?, ?> getRegionForContext(RegionFunctionContext regionFunctionContext) {
Region<?, ?> region = regionFunctionContext.getDataSet();
if (PartitionRegionHelper.isPartitionedRegion(region)) {
if (logger.isDebugEnabled()) {
logger.debug("this is a partitioned region - filtering local data for context");
}
region = PartitionRegionHelper.getLocalDataForContext(regionFunctionContext);
}
if (logger.isDebugEnabled()) {
logger.debug("region contains " + region.size() + " items");
}
return region;
}
private static int getArgumentTypePosition(Method method, Class<?> requiredType) {
int position = -1;
int i = 0;
for (Class<?> clazz: method.getParameterTypes()) {
if (requiredType.equals(clazz)) {
Assert.state(position < 0, String.format("Method %s signature cannot contain more than one parameter of type %s."
,method.getName(),requiredType.getName()));
position = i;
}
i++;
}
return position;
}
}

View File

@@ -1,46 +0,0 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function;
import java.io.Serializable;
import java.util.List;
import java.util.Set;
import com.gemstone.gemfire.cache.execute.Function;
/**
* @author David Turanski
*
* @param <T>
*/
public interface GemfireFunctionOperations<T> {
public abstract List<T> executeOnRegion(Function function, String regionId, Serializable... args);
public abstract T executeOnRegionAndExtract(Function function, String regionId, Serializable... args);
public abstract List<T> executeOnRegion(Function function, String regionId, Set<?> keys, Serializable... args);
public abstract List<T> executeOnRegion(String functionId, String regionId, Serializable... args);
public abstract List<T> executeOnRegion(String functionId, String regionId, Set<?> keys, Serializable... args);
public abstract T executeOnRegion(String regionId, GemfireFunctionCallback<T> callback);
public abstract List<T> executeOnServers(Function function, Serializable... args);
public abstract List<T> executeOnServers(String functionId, Serializable... args);
public abstract T executeOnServers(GemfireFunctionCallback<T> callback);
}

View File

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

View File

@@ -1,168 +0,0 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function;
import java.io.Serializable;
import java.util.List;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.RegionService;
import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.Function;
import com.gemstone.gemfire.cache.execute.FunctionService;
/**
* @author David Turanski
*
*/
public class GemfireFunctionTemplate<T> implements InitializingBean, GemfireFunctionOperations<T> {
/** Logger available to subclasses */
protected final Log log = LogFactory.getLog(getClass());
private RegionService cache;
private long timeout;
/**
*
* @param cache
*/
public GemfireFunctionTemplate (RegionService cache) {
this.cache = cache;
afterPropertiesSet();
}
public void afterPropertiesSet() {
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.GemfireFunctionOperations#executeOnRegion(com.gemstone.gemfire.cache.execute.Function, java.lang.String, java.io.Serializable)
*/
public List<T> executeOnRegion(Function function, String regionId, Serializable... args) {
Region<?,?> region = getRegion(regionId);
Assert.notNull(region,"Region '" + regionId + "' not found");
RegionFunctionExecution<T> execution = new RegionFunctionExecution<T>(region, function, args);
execution.setTimeout(this.timeout);
return execution.execute();
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.GemfireFunctionOperations#executeOnRegionAndExtract(com.gemstone.gemfire.cache.execute.Function, java.lang.String, java.io.Serializable)
*/
public T executeOnRegionAndExtract(Function function, String regionId, Serializable... args) {
Region<?,?> region = getRegion(regionId);
Assert.notNull(region,"Region '" + regionId + "' not found");
RegionFunctionExecution<T> execution = new RegionFunctionExecution<T>(region, function, args);
execution.setTimeout(this.timeout);
return execution.executeAndExtract();
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.GemfireFunctionOperations#executeOnRegion(com.gemstone.gemfire.cache.execute.Function, java.lang.String, java.util.Set, java.io.Serializable)
*/
public List<T> executeOnRegion(Function function, String regionId, Set<?> keys, Serializable... args) {
Region<?,?> region = getRegion(regionId);
Assert.notNull(region,"Region '" + regionId + "' not found");
RegionFunctionExecution<T> execution = new RegionFunctionExecution<T>(region, function, args);
execution.setKeys(keys);
execution.setTimeout(this.timeout);
return execution.execute();
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.GemfireFunctionOperations#executeOnRegion(java.lang.String, java.lang.String, java.io.Serializable)
*/
public List<T> executeOnRegion(String functionId, String regionId, Serializable... args) {
Region<?,?> region = getRegion(regionId);
Assert.notNull(region,"Region '" + regionId + "' not found");
RegionFunctionExecution<T> execution = new RegionFunctionExecution<T>(region, functionId, args);
execution.setTimeout(this.timeout);
return execution.execute();
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.GemfireFunctionOperations#executeOnRegion(java.lang.String, java.lang.String, java.util.Set, java.io.Serializable)
*/
public List<T> executeOnRegion(String functionId, String regionId, Set<?> keys, Serializable... args) {
Region<?,?> region = getRegion(regionId);
Assert.notNull(region,"Region '" + regionId + "' not found");
RegionFunctionExecution<T> execution = new RegionFunctionExecution<T>(region, functionId, args);
execution.setKeys(keys);
execution.setTimeout(this.timeout);
return execution.execute();
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.GemfireFunctionOperations#executeOnRegion(java.lang.String, org.springframework.data.gemfire.function.GemfireFunctionCallback)
*/
public T executeOnRegion(String regionId, GemfireFunctionCallback<T> callback ) {
Region<?,?> region = getRegion(regionId);
Assert.notNull(region,"Region '" + regionId + "' not found");
Execution execution = FunctionService.onRegion(region);
return callback.doInGemfire(execution);
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.GemfireFunctionOperations#executeOnServers(com.gemstone.gemfire.cache.execute.Function, java.io.Serializable)
*/
public List<T> executeOnServers(Function function, Serializable... args) {
ServersFunctionExecution<T> execution = new ServersFunctionExecution<T>(this.cache, function, args);
execution.setTimeout(this.timeout);
return execution.execute();
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.GemfireFunctionOperations#executeOnServers(java.lang.String, java.io.Serializable)
*/
public List<T> executeOnServers(String functionId, Serializable... args) {
ServersFunctionExecution<T> execution = new ServersFunctionExecution<T>(this.cache, functionId, args);
execution.setTimeout(this.timeout);
return execution.execute();
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.GemfireFunctionOperations#executeOnServers(org.springframework.data.gemfire.function.GemfireFunctionCallback)
*/
public T executeOnServers(GemfireFunctionCallback<T> callback ) {
Execution execution = FunctionService.onServers(this.cache);
return callback.doInGemfire(execution);
}
public Region<?,?> getRegion(String regionId) {
return this.cache.getRegion(regionId);
}
public void setTimeout(long timeout) {
this.timeout = timeout;
}
public long getTimeout() {
return timeout;
}
}

View File

@@ -1,51 +0,0 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function;
import java.io.Serializable;
import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.Function;
import com.gemstone.gemfire.cache.execute.FunctionService;
import com.gemstone.gemfire.distributed.DistributedSystem;
/**
* @author David Turanski
*
*/
public class MemberFunctionExecution extends FunctionExecution<Object> {
private final DistributedSystem distributedSystem;
/**
* @param functionId
* @param args
*/
public MemberFunctionExecution(DistributedSystem distributedSystem, Function function, Serializable... args) {
super(function, args);
this.distributedSystem = distributedSystem;
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.FunctionExecution#getExecution()
*/
@Override
protected Execution getExecution() {
return FunctionService.onMember(this.distributedSystem, this.distributedSystem.getDistributedMember());
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at

View File

@@ -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);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at

View File

@@ -1,60 +0,0 @@
/*
* Copyright 2002-2011 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function;
import java.io.Serializable;
import com.gemstone.gemfire.cache.RegionService;
import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.Function;
import com.gemstone.gemfire.cache.execute.FunctionService;
/**
* @author David Turanski
*
*/
public class ServerFunctionExecution<T> extends FunctionExecution<T> {
private final RegionService regionService;
/**
*
* @param regionService e.g., Cache,Client, or GemFireCache
* @param function
* @param args
*/
public ServerFunctionExecution(RegionService regionService, Function function, Serializable... args) {
super(function, args);
this.regionService = regionService;
}
/**
*
* @param regionService e.g., Cache,Client, or GemFireCache
* @param functionId
* @param args
*/
public ServerFunctionExecution(RegionService regionService, String functionId, Serializable... args) {
super(functionId, args);
this.regionService = regionService;
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.FunctionExecution#getExecution()
*/
@Override
protected Execution getExecution() {
return FunctionService.onServer(this.regionService);
}
}

View File

@@ -0,0 +1,76 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.config;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.support.AbstractBeanDefinition;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.util.Assert;
/**
* Base class for function execution bean definition builders
* @author David Turanski
*
*/
abstract class AbstractFunctionExecutionBeanDefinitionBuilder {
protected final Log log = LogFactory.getLog(this.getClass());
protected final FunctionExecutionConfiguration configuration;
/**
*
* @param configuration the configuration values
*/
AbstractFunctionExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) {
Assert.notNull(configuration);
this.configuration = configuration;
}
/**
* Build the bean definition
* @param registry
* @return
*/
BeanDefinition build(BeanDefinitionRegistry registry) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.rootBeanDefinition(getFunctionProxyFactoryBeanClass());
builder.addConstructorArgValue(configuration.getFunctionExecutionInterface());
BeanDefinitionBuilder functionTemplateBuilder = getGemfireOperationsBeanDefinitionBuilder(registry);
functionTemplateBuilder.setLazyInit(true);
AbstractBeanDefinition functionTemplate = functionTemplateBuilder
.getBeanDefinition();
String functionTemplateName = BeanDefinitionReaderUtils.registerWithGeneratedName(functionTemplate, registry);
builder.addConstructorArgReference(functionTemplateName);
// builder.addConstructorArgValue(functionTemplate);
return builder.getBeanDefinition();
}
/*
* Subclasses implement to specify the types to uses.
*/
protected abstract Class<?> getFunctionProxyFactoryBeanClass();
protected abstract BeanDefinitionBuilder getGemfireOperationsBeanDefinitionBuilder(BeanDefinitionRegistry registry);
}

View File

@@ -0,0 +1,204 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.config;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
import org.springframework.context.annotation.FilterType;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.annotation.AnnotationAttributes;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.core.type.filter.AnnotationTypeFilter;
import org.springframework.core.type.filter.AssignableTypeFilter;
import org.springframework.core.type.filter.TypeFilter;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
/**
* Annotation based configuration source for function executions
*
* @author David Turanski
*
*/
class AnnotationFunctionExecutionConfigurationSource implements FunctionExecutionConfigurationSource {
private static Log logger = LogFactory.getLog(AnnotationFunctionExecutionConfigurationSource.class);
private static final String BASE_PACKAGES = "basePackages";
private static final String BASE_PACKAGE_CLASSES = "basePackageClasses";
private final AnnotationMetadata metadata;
private final AnnotationAttributes attributes;
private static Set<Class<? extends Annotation>> functionExecutionAnnotationTypes;
static {
functionExecutionAnnotationTypes = new HashSet<Class<? extends Annotation>>();
functionExecutionAnnotationTypes.add(OnRegion.class);
functionExecutionAnnotationTypes.add(OnServer.class);
functionExecutionAnnotationTypes.add(OnServers.class);
functionExecutionAnnotationTypes.add(OnMember.class);
functionExecutionAnnotationTypes.add(OnMembers.class);
}
/**
* Creates a new {@link AnnotationFunctionExecutionConfigurationSource} from the given {@link AnnotationMetadata} and
* annotation.
*
* @param metadata must not be {@literal null}.
*/
AnnotationFunctionExecutionConfigurationSource(AnnotationMetadata metadata) {
Assert.notNull(metadata);
this.attributes = new AnnotationAttributes(metadata.getAnnotationAttributes(EnableGemfireFunctionExecutions.class.getName()));
this.metadata = metadata;
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.FunctionExecutionConfigurationSource#getSource()
*/
@Override
public Object getSource() {
// TODO Auto-generated method stub
return this.metadata;
}
static Set<Class<? extends Annotation>> getFunctionExecutionAnnotationTypes() {
return functionExecutionAnnotationTypes;
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.FunctionExecutionConfigurationSource#getBasePackages()
*/
@Override
public Iterable<String> getBasePackages() {
String[] value = attributes.getStringArray("value");
String[] basePackages = attributes.getStringArray(BASE_PACKAGES);
Class<?>[] basePackageClasses = attributes.getClassArray(BASE_PACKAGE_CLASSES);
// Default configuration - return package of annotated class
if (value.length == 0 && basePackages.length == 0 && basePackageClasses.length == 0) {
String className = metadata.getClassName();
return Collections.singleton(className.substring(0, className.lastIndexOf('.')));
}
Set<String> packages = new HashSet<String>();
packages.addAll(Arrays.asList(value));
packages.addAll(Arrays.asList(basePackages));
for (Class<?> typeName : basePackageClasses) {
packages.add(ClassUtils.getPackageName(typeName));
}
return packages;
}
@Override
public Collection<ScannedGenericBeanDefinition> getCandidates(ResourceLoader loader) {
ClassPathScanningCandidateComponentProvider scanner = new FunctionExecutionComponentProvider(getIncludeFilters(),functionExecutionAnnotationTypes);
scanner.setResourceLoader(loader);
for (TypeFilter filter : getExcludeFilters()) {
scanner.addExcludeFilter(filter);
}
Set<ScannedGenericBeanDefinition> result = new HashSet<ScannedGenericBeanDefinition>();
for (String basePackage : getBasePackages()) {
logger.debug("scanning package " + basePackage);
Collection<BeanDefinition> components = scanner.findCandidateComponents(basePackage);
for (BeanDefinition definition : components) {
result.add((ScannedGenericBeanDefinition)definition);
}
}
return result;
}
protected Iterable<TypeFilter> getIncludeFilters() {
return parseFilters("includeFilters");
}
protected Iterable<TypeFilter> getExcludeFilters() {
return parseFilters("excludeFilters");
}
private Set<TypeFilter> parseFilters(String attributeName) {
Set<TypeFilter> result = new HashSet<TypeFilter>();
AnnotationAttributes[] filters = attributes.getAnnotationArray(attributeName);
for (AnnotationAttributes filter : filters) {
result.addAll(typeFiltersFor(filter));
}
return result;
}
/**
* Copy of {@code ComponentScanAnnotationParser#typeFiltersFor}.
*
* @param filterAttributes
* @return
*/
private List<TypeFilter> typeFiltersFor(AnnotationAttributes filterAttributes) {
List<TypeFilter> typeFilters = new ArrayList<TypeFilter>();
FilterType filterType = filterAttributes.getEnum("type");
for (Class<?> filterClass : filterAttributes.getClassArray("value")) {
switch (filterType) {
case ANNOTATION:
Assert.isAssignable(Annotation.class, filterClass, "An error occured when processing a @ComponentScan "
+ "ANNOTATION type filter: ");
@SuppressWarnings("unchecked")
Class<Annotation> annoClass = (Class<Annotation>) filterClass;
typeFilters.add(new AnnotationTypeFilter(annoClass));
break;
case ASSIGNABLE_TYPE:
typeFilters.add(new AssignableTypeFilter(filterClass));
break;
case CUSTOM:
Assert.isAssignable(TypeFilter.class, filterClass, "An error occured when processing a @ComponentScan "
+ "CUSTOM type filter: ");
typeFilters.add(BeanUtils.instantiateClass(filterClass, TypeFilter.class));
break;
default:
throw new IllegalArgumentException("unknown filter type " + filterType);
}
}
return typeFilters;
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.config;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.springframework.context.annotation.ComponentScan.Filter;
import org.springframework.context.annotation.Import;
/**
* Enables classpath scanning for interfaces annotated as GemFire function executions (function invocations).
* These include interfaces annotated with one of {code} @OnRegion, @OnServer, @OnServers, @OnMember, @OnMembers{code}
*
* @author David Turanski
*
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@Import(FunctionExecutionBeanDefinitionRegistrar.class)
public @interface EnableGemfireFunctionExecutions {
/**
* Alias for the {@link #basePackages()} attribute. Allows for more concise annotation declarations e.g.:
* {@code @EnableGemfireRepositories("org.my.pkg")} instead of
* {@code @EnableGemfireRepositories(basePackages="org.my.pkg")}.
*/
String[] value() default {};
/**
* Base packages to scan for annotated components. {@link #value()} is an alias for (and mutually exclusive with) this
* attribute. Use {@link #basePackageClasses()} for a type-safe alternative to String-based package names.
*/
String[] basePackages() default {};
/**
* Type-safe alternative to {@link #basePackages()} for specifying the packages to scan for annotated components. The
* package of each class specified will be scanned. Consider creating a special no-op marker class or interface in
* each package that serves no purpose other than being referenced by this attribute.
*/
Class<?>[] basePackageClasses() default {};
/**
* Specifies which types are eligible for component scanning. Further narrows the set of candidate components from
* everything in {@link #basePackages()} to everything in the base packages that matches the given filter or filters.
*/
Filter[] includeFilters() default {};
/**
* Specifies which types are not eligible for component scanning.
*/
Filter[] excludeFilters() default {};
}

View File

@@ -19,9 +19,14 @@ import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.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 {};
}

View File

@@ -0,0 +1,31 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
*
* Used to inject a set of cache keys into a function execution, The annotated parameter must be of type
* {@link Set}. This is used by the function invocation to specify a set of keys of interest and also to define
* an additional parameter on the function implementation method containing the filter.
* @author David Turanski
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.PARAMETER})
public @interface Filter {
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.config;
/**
*
* Maps the annotation type to the corresponding function execution bean definition builder
* @author David Turanski
*
*/
abstract class FunctionExecutionBeanDefinitionBuilderFactory {
static AbstractFunctionExecutionBeanDefinitionBuilder newInstance(FunctionExecutionConfiguration configuration) {
String functionExectionAnnotation = configuration.getAnnotationType();
if (functionExectionAnnotation.equals(OnRegion.class.getName())) {
return new OnRegionExecutionBeanDefinitionBuilder(configuration);
}
if (functionExectionAnnotation.equals(OnServer.class.getName())) {
return new OnServerExecutionBeanDefinitionBuilder(configuration);
}
if (functionExectionAnnotation.equals(OnServers.class.getName())) {
return new OnServersExecutionBeanDefinitionBuilder(configuration);
}
if (functionExectionAnnotation.equals(OnMember.class.getName())) {
return new OnMemberExecutionBeanDefinitionBuilder(configuration);
}
if (functionExectionAnnotation.equals(OnMembers.class.getName())) {
return new OnMembersExecutionBeanDefinitionBuilder(configuration);
}
return null;
}
}

View File

@@ -0,0 +1,96 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.config;
import java.util.HashSet;
import java.util.Set;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.ResourceLoader;
import org.springframework.core.type.AnnotationMetadata;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* {@link ImportBeanDefinitionRegistrar} for {code} @EnableGemfireFunctionExecutions {code}
* Scans for interfaces annotated with one of {code} @OnRegion, @OnServer, @OnServers, @OnMember, @OnMembers {code}
* @author David Turanski
*
*/
public class FunctionExecutionBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
private static Log logger = LogFactory.getLog(FunctionExecutionBeanDefinitionRegistrar.class);
/* (non-Javadoc)
* @see org.springframework.context.annotation.ImportBeanDefinitionRegistrar#registerBeanDefinitions(org.springframework.core.type.AnnotationMetadata, org.springframework.beans.factory.support.BeanDefinitionRegistry)
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {
logger.debug("registering bean definitions...");
ResourceLoader resourceLoader = new DefaultResourceLoader();
AnnotationFunctionExecutionConfigurationSource configurationSource = new AnnotationFunctionExecutionConfigurationSource(
annotationMetadata);
Set<String> functionExecutionAnnotationTypes = new HashSet<String>(
AnnotationFunctionExecutionConfigurationSource.getFunctionExecutionAnnotationTypes().size());
for (Class<?> annotation : AnnotationFunctionExecutionConfigurationSource.getFunctionExecutionAnnotationTypes()) {
functionExecutionAnnotationTypes.add(annotation.getName());
}
for (ScannedGenericBeanDefinition beanDefinition : configurationSource.getCandidates(resourceLoader)) {
String functionExecutionAnnotation = getFunctionExecutionAnnotation(beanDefinition,
functionExecutionAnnotationTypes);
Assert.notNull(functionExecutionAnnotation);
String beanName = (String) beanDefinition.getMetadata()
.getAnnotationAttributes(functionExecutionAnnotation).get("id");
if (!StringUtils.hasLength(beanName)) {
beanName = BeanDefinitionReaderUtils.generateBeanName(beanDefinition, registry);
}
AbstractFunctionExecutionBeanDefinitionBuilder builder = FunctionExecutionBeanDefinitionBuilderFactory
.newInstance(new FunctionExecutionConfiguration(beanDefinition, functionExecutionAnnotation));
registry.registerBeanDefinition(beanName, builder.build(registry));
}
}
private String getFunctionExecutionAnnotation(ScannedGenericBeanDefinition beanDefinition,
Set<String> functionExecutionAnnotationTypes) {
Set<String> annotationTypes = beanDefinition.getMetadata().getAnnotationTypes();
String functionExecutionAnnotation = null;
for (String annotation : annotationTypes) {
if (functionExecutionAnnotationTypes.contains(annotation)) {
Assert.isNull(functionExecutionAnnotation, String.format(
"interface %s contains multiple function execution annotations: %s, %s",
beanDefinition.getBeanClassName(), functionExecutionAnnotation, annotation));
functionExecutionAnnotation = annotation;
}
}
return functionExecutionAnnotation;
}
}

View File

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

View File

@@ -0,0 +1,64 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.config;
import java.util.Map;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.util.Assert;
/**
* Function execution configuration used by bean definition builders
*
* @author David Turanski
*
*/
class FunctionExecutionConfiguration {
private final Map<String,Object> attributes;
private Class<?> functionExecutionInterface;
private final String annotationType;
FunctionExecutionConfiguration(ScannedGenericBeanDefinition beanDefinition, String annotationType) {
this.attributes = beanDefinition.getMetadata().getAnnotationAttributes(annotationType,true);
try {
this.functionExecutionInterface = beanDefinition.resolveBeanClass(beanDefinition.getClass().getClassLoader());
Assert.isTrue(functionExecutionInterface.isInterface(),
String.format("The annotation %s only applies to an interface. It is not valid for the type %s",
annotationType, functionExecutionInterface.getName()));
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
this.annotationType = annotationType;
}
Class<?> getFunctionExecutionInterface() {
return this.functionExecutionInterface;
}
Map<String, Object> getAttributes() {
return this.attributes;
}
Object getAttribute(String name) {
return attributes.get(name);
}
String getAnnotationType() {
return this.annotationType;
}
}

View File

@@ -0,0 +1,50 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.config;
import java.util.Collection;
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
import org.springframework.core.io.ResourceLoader;
/**
* Interface for function execution configuration sources (e.g., annotation or XML configuration) to configure
* classpath scanning of annotated interfaces to implement proxies that invoke Gemfire functions
*
* @author David Turanski
*
*/
interface FunctionExecutionConfigurationSource {
/**
* Returns the actual source object that the configuration originated from. Will be used by the tooling to give visual
* feedback on where the repository instances actually come from.
*
* @return must not be {@literal null}.
*/
Object getSource();
/**
* Returns the base packages the repository interfaces shall be found under.
*
* @return must not be {@literal null}.
*/
Iterable<String> getBasePackages();
/**
* Returns the scanned bean definitions
*
* @param loader
* @return
*/
Collection<ScannedGenericBeanDefinition> getCandidates(ResourceLoader loader);
}

View File

@@ -0,0 +1,33 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to bind an interface method to a GemFire function id
* @author David Turanski
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.METHOD})
public @interface FunctionId {
/**
* The name of the registered function
* @return the function id
*/
String value();
}

View File

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

View File

@@ -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());
}
}
}
}
}

View File

@@ -0,0 +1,36 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.config;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;
/**
* and {@link ImportBeanDefinitionRegistrar} to register the {@link GemfireFunctionBeanPostProcessor}
*
* @author David Turanski
*
*/
public class GemfireFunctionPostBeanProcessorRegistrar implements ImportBeanDefinitionRegistrar {
/* (non-Javadoc)
* @see org.springframework.context.annotation.ImportBeanDefinitionRegistrar#registerBeanDefinitions(org.springframework.core.type.AnnotationMetadata, org.springframework.beans.factory.support.BeanDefinitionRegistry)
*/
@Override
public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
// TODO Auto-generated method stub
}
}

View File

@@ -12,35 +12,49 @@
*/
package org.springframework.data.gemfire.function.config;
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;
}
}

View File

@@ -0,0 +1,65 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.config;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.data.gemfire.function.execution.GemfireFunctionProxyFactoryBean;
import org.springframework.util.StringUtils;
/**
* A base class for OnMember and OnMembers function execution bean definition builders.
*
* @author David Turanski
*
*/
abstract class MemberBasedExecutionBeanDefinitionBuilder extends AbstractFunctionExecutionBeanDefinitionBuilder {
/**
* @param configuration
*/
public MemberBasedExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) {
super(configuration);
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.AbstractFunctionExecutionBeanDefinitionBuilder#getGemfireOperationsBeanDefinitionBuilder(org.springframework.beans.factory.support.BeanDefinitionRegistry)
*/
@Override
protected BeanDefinitionBuilder getGemfireOperationsBeanDefinitionBuilder(BeanDefinitionRegistry registry) {
BeanDefinitionBuilder functionTemplateBuilder = BeanDefinitionBuilder.genericBeanDefinition(getGemfireOperationsClass());
String groups = (String)configuration.getAttribute("groups");
if (StringUtils.hasText(groups)) {
functionTemplateBuilder.addConstructorArgValue(StringUtils.commaDelimitedListToStringArray(groups));
}
return functionTemplateBuilder;
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.AbstractFunctionExecutionBeanDefinitionBuilder#getFunctionProxyFactoryBeanClass()
*/
@Override
protected Class<?> getFunctionProxyFactoryBeanClass() {
return GemfireFunctionProxyFactoryBean.class;
}
protected abstract Class<?> getGemfireOperationsClass();
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to declare an interface as a GemFire OnMember Function Execution
*
* @author David Turanski
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface OnMember {
/**
* The bean name and also the default name of the registered function, if single method on the interface.
* If multiple methods declared use the (@link FunctionId) annotation on each method
* @return the function id
*/
String id() default "";
//TODO SpEL expression for DistributedMember?
/**
* groups
*/
String groups() default "";
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.config;
import org.springframework.data.gemfire.function.execution.GemfireOnMemberFunctionTemplate;
/**
*
* @author David Turanski
*
*/
class OnMemberExecutionBeanDefinitionBuilder extends MemberBasedExecutionBeanDefinitionBuilder {
/**
* @param configuration
*/
OnMemberExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) {
super(configuration);
// TODO Auto-generated constructor stub
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.MemberBasedExecutionBeanDefinitionBuilder#getGemfireOperationsClass()
*/
@Override
protected Class<?> getGemfireOperationsClass() {
return GemfireOnMemberFunctionTemplate.class;
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to declare an interface as a GemFire OnMembers Function Execution
* @author David Turanski
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface OnMembers {
/**
* The bean name and also the default name of the registered function, if single method on the interface.
* If multiple methods declared use the (@link FunctionId) annotation on each method
* @return the function id
*/
String id() default "";
//TODO SpEL expression for DistributedMembers?
/**
* groups
*/
String groups() default "";
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.config;
import org.springframework.data.gemfire.function.execution.GemfireOnMembersFunctionTemplate;
/**
* @author David Turanski
*
*/
class OnMembersExecutionBeanDefinitionBuilder extends MemberBasedExecutionBeanDefinitionBuilder {
/**
* @param configuration
*/
OnMembersExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) {
super(configuration);
// TODO Auto-generated constructor stub
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.MemberBasedExecutionBeanDefinitionBuilder#getGemfireOperationsClass()
*/
@Override
protected Class<?> getGemfireOperationsClass() {
return GemfireOnMembersFunctionTemplate.class;
}
}

View File

@@ -0,0 +1,41 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to declare an interface as a GemFire OnRegion Function Execution
* @author David Turanski
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface OnRegion {
/**
* The bean name and also the default name of the registered function, if single method on the interface.
* If multiple methods declared use the (@link FunctionId) annotation on each method
* @return the function id
*/
String id() default "";
/**
* The reference to the bean id of the region
* @return the region id
*/
String region();
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.config;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.data.gemfire.function.execution.GemfireOnRegionFunctionTemplate;
import org.springframework.data.gemfire.function.execution.OnRegionFunctionProxyFactoryBean;
/**
* @author David Turanski
*
*/
class OnRegionExecutionBeanDefinitionBuilder extends AbstractFunctionExecutionBeanDefinitionBuilder {
/**
* @param configuration
*/
OnRegionExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) {
super(configuration);
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.AbstractFunctionExecutionBeanDefinitionBuilder#getGemfireOperationsBeanDefinitionBuilder(org.springframework.beans.factory.support.BeanDefinitionRegistry)
*/
@Override
protected BeanDefinitionBuilder getGemfireOperationsBeanDefinitionBuilder(BeanDefinitionRegistry registry) {
BeanDefinitionBuilder functionTemplateBuilder = BeanDefinitionBuilder.genericBeanDefinition(GemfireOnRegionFunctionTemplate.class);
functionTemplateBuilder.addConstructorArgReference((String)configuration.getAttribute("region"));
return functionTemplateBuilder;
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.AbstractFunctionExecutionBeanDefinitionBuilder#getFunctionProxyFactoryBeanClass()
*/
@Override
protected Class<?> getFunctionProxyFactoryBeanClass() {
return OnRegionFunctionProxyFactoryBean.class;
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to declare an interface as a GemFire OnServer Function Execution
* @author David Turanski
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface OnServer {
/**
* The bean name and also the default name of the registered function, if single method on the interface.
* If multiple methods declared use the (@link FunctionId) annotation on each method
* @return the function id
*/
String id() default "";
/**
* The pool bean id (optional)
* @return
*/
String pool() default "";
/**
* A reference to the cache
*/
String cache() default "";
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.config;
import org.springframework.data.gemfire.function.execution.GemfireOnServerFunctionTemplate;
/**
* @author David Turanski
*
*/
class OnServerExecutionBeanDefinitionBuilder extends ServerBasedExecutionBeanDefinitionBuilder {
/**
* @param configuration
*/
OnServerExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) {
super(configuration);
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.ServerBasedExecutionBeanDefinitionBuilder#getGemfireOperationsClass()
*/
@Override
protected Class<?> getGemfireOperationsClass() {
return GemfireOnServerFunctionTemplate.class;
}
}

View File

@@ -0,0 +1,46 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Annotation to declare an interface as a GemFire OnServers Function Execution
* @author David Turanski
*
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface OnServers {
/**
* The bean name and also the default name of the registered function, if single method on the interface.
* If multiple methods declared use the (@link FunctionId) annotation on each method
* @return the function id
*/
String id() default "";
/**
* The pool bean name (optional)
* @return
*/
String pool() default "";
/**
* A reference to the cache
*/
String cache() default "gemfireCache";
}

View File

@@ -0,0 +1,37 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.config;
import org.springframework.data.gemfire.function.execution.GemfireOnServersFunctionTemplate;
/**
* @author David Turanski
*
*/
class OnServersExecutionBeanDefinitionBuilder extends ServerBasedExecutionBeanDefinitionBuilder {
/**
* @param configuration
*/
OnServersExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) {
super(configuration);
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.ServerBasedExecutionBeanDefinitionBuilder#getGemfireOperationsClass()
*/
@Override
protected Class<?> getGemfireOperationsClass() {
return GemfireOnServersFunctionTemplate.class;
}
}

View File

@@ -23,11 +23,11 @@ import java.lang.annotation.Target;
* {@link Map}. The contents depends on the region configuration (for a partitioned region, this will
* 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 "";
}

View File

@@ -0,0 +1,75 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.config;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.data.gemfire.config.GemfireConstants;
import org.springframework.data.gemfire.function.execution.GemfireFunctionProxyFactoryBean;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
/**
* @author David Turanski
*
*/
abstract class ServerBasedExecutionBeanDefinitionBuilder extends AbstractFunctionExecutionBeanDefinitionBuilder {
/**
* @param configuration
*/
ServerBasedExecutionBeanDefinitionBuilder(FunctionExecutionConfiguration configuration) {
super(configuration);
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.AbstractFunctionExecutionBeanDefinitionBuilder#getGemfireOperationsBeanDefinitionBuilder(org.springframework.beans.factory.support.BeanDefinitionRegistry)
*/
@Override
protected BeanDefinitionBuilder getGemfireOperationsBeanDefinitionBuilder(BeanDefinitionRegistry registry) {
BeanDefinitionBuilder functionTemplateBuilder = BeanDefinitionBuilder.genericBeanDefinition(getGemfireOperationsClass());
String pool = (String)configuration.getAttribute("pool");
String cache = (String)configuration.getAttribute("cache");
Assert.state(!(StringUtils.hasText(pool) && StringUtils.hasText(cache)),
String.format("invalid configuration for interface %s. Cannot specify both 'pool' and 'cache'",
configuration.getFunctionExecutionInterface().getName()));
if (StringUtils.hasText(pool)) {
functionTemplateBuilder.addConstructorArgReference(pool);
} else {
if (!StringUtils.hasText(cache)) {
cache = GemfireConstants.DEFAULT_GEMFIRE_CACHE_NAME;
}
functionTemplateBuilder.addConstructorArgReference(cache);
}
return functionTemplateBuilder;
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.AbstractFunctionExecutionBeanDefinitionBuilder#getFunctionProxyFactoryBeanClass()
*/
@Override
protected Class<?> getFunctionProxyFactoryBeanClass() {
return GemfireFunctionProxyFactoryBean.class;
}
protected abstract Class<?> getGemfireOperationsClass();
}

View File

@@ -0,0 +1,91 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.execution;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.Function;
/**
*
* The base class for Gemfire function templates used to invoke Gemfire functions
* @author David Turanski
*
*/
abstract class AbstractFunctionTemplate implements GemfireFunctionOperations {
protected Log log = LogFactory.getLog(this.getClass());
protected long timeout;
@Override
public <T> Iterable<T> execute(Function function, Object... args) {
FunctionExecution functionExecution = getFunctionExecution()
.setArgs(args)
.setFunction(function)
.setTimeout(timeout);
return execute(functionExecution);
}
@Override
public <T> T executeAndExtract(Function function, Object... args) {
FunctionExecution functionExecution = getFunctionExecution()
.setArgs(args)
.setFunction(function)
.setTimeout(timeout);
return executeAndExtract(functionExecution);
}
@Override
public <T> Iterable<T> execute(String functionId, Object... args) {
FunctionExecution functionExecution = getFunctionExecution()
.setArgs(args)
.setFunctionId(functionId)
.setTimeout(timeout);
return execute(functionExecution);
}
@Override
public <T> T executeAndExtract(String functionId, Object... args) {
FunctionExecution functionExecution = getFunctionExecution()
.setArgs(args)
.setFunctionId(functionId)
.setTimeout(timeout);
return executeAndExtract(functionExecution);
}
@Override
public <T> T execute(GemfireFunctionCallback<T> callback) {
Execution execution = getFunctionExecution().getExecution();
return callback.doInGemfire(execution);
}
protected <T> Iterable<T> execute(FunctionExecution execution) {
execution.setTimeout(timeout);
return execution.execute();
}
protected <T> T executeAndExtract(FunctionExecution execution) {
execution.setTimeout(timeout);
return execution.executeAndExtract();
}
public void setTimeout(long timeout) {
this.timeout = timeout;
}
protected abstract FunctionExecution getFunctionExecution();
}

View File

@@ -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();
}
}

View File

@@ -0,0 +1,39 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.execution;
import java.lang.reflect.Method;
/**
* @author David Turanski
*
*/
class DefaultFunctionExecutionMethodMetadata extends FunctionExecutionMethodMetadata<MethodMetadata> {
/**
* @param serviceInterface
*/
public DefaultFunctionExecutionMethodMetadata(Class<?> serviceInterface) {
super(serviceInterface);
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.FunctionExecutionMethodMetadata#newMetadataInstance(java.lang.reflect.Method)
*/
@Override
protected MethodMetadata newMetadataInstance(Method method) {
return new MethodMetadata(method);
}
}

View File

@@ -0,0 +1,29 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.execution;
import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.FunctionService;
/**
* @author David Turanski
*
*/
public class DefaultMemberFunctionExecution extends FunctionExecution {
@Override
protected Execution getExecution() {
return FunctionService.onMember();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* 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);
}
}

View File

@@ -0,0 +1,42 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.execution;
import java.util.Set;
import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.FunctionService;
import com.gemstone.gemfire.distributed.DistributedMember;
/**
* @author David Turanski
*
*/
public class DistributedMembersFunctionExecution extends FunctionExecution {
private final Set<DistributedMember> distributedMembers;
/**
*
* @param distributedMembers
*/
public DistributedMembersFunctionExecution(Set<DistributedMember> distributedMembers ) {
super( );
this.distributedMembers = distributedMembers;
}
@Override
protected Execution getExecution() {
return FunctionService.onMembers(this.distributedMembers);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* 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;
}
}

View File

@@ -0,0 +1,94 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.execution;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;
import org.springframework.data.gemfire.function.config.FunctionId;
import org.springframework.util.Assert;
import org.springframework.util.ReflectionUtils;
/**
* Base class for method level metadata for a function execution interface. This is used at runtime by the
* function execution proxy to create the corresponding Gemfire function {@link Execution}
*
* @author David Turanski
*
*/
abstract class FunctionExecutionMethodMetadata<T extends MethodMetadata > {
protected final Map<Method, T> methodMetadata = new HashMap<Method, T>();
private final boolean singletonInterface;
public FunctionExecutionMethodMetadata(final Class<?> serviceInterface) {
this.singletonInterface = serviceInterface.getMethods().length == 1;
ReflectionUtils.doWithMethods(serviceInterface, new ReflectionUtils.MethodCallback() {
@Override
public void doWith(Method method) throws IllegalArgumentException, IllegalAccessException {
T mmd = newMetadataInstance(method);
if (mmd.getFunctionId() == null) {
mmd.setFunctionId(serviceInterface.getName() + "." + method.getName());
}
methodMetadata.put(method, mmd);
}
});
}
protected abstract T newMetadataInstance(Method method);
T getMethodMetadata(Method method) {
return methodMetadata.get(method);
}
boolean isSingletonInterface() {
return this.singletonInterface;
}
T getSingletonMethodMetada() {
Assert.isTrue(isSingletonInterface(),"this is not a singleton interface.");
return methodMetadata.values().iterator().next();
}
}
class MethodMetadata {
private String functionId;
public MethodMetadata(Method method) {
String annotatedFunctionId = annotatedFunctionId(method);
this.functionId = (annotatedFunctionId == null) ? null : annotatedFunctionId;
}
/**
* @return the functionId
*/
public String getFunctionId() {
return functionId;
}
public void setFunctionId(String functionId) {
this.functionId = functionId;
}
private String annotatedFunctionId(Method method) {
FunctionId functionIdAnnotation = method.getAnnotation(FunctionId.class);
return (functionIdAnnotation == null) ? null : functionIdAnnotation.value();
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* 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
*
*/

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.execution;
import com.gemstone.gemfire.cache.execute.Function;
/**
*
* An interface for invoking Gemfire functions
*
* @author David Turanski
*
* @param <T> the preferred return type
*/
public interface GemfireFunctionOperations {
/**
* Execute an unregistered function
* @param function the function
* @param args calling arguments
* @return the contents of the results collector
*/
public abstract <T> Iterable<T> execute(Function function, Object... args);
/**
* Execute an unregistered function with an expected singleton result
* @param function the function
* @param args calling arguments
* @return the first item in the results collector
*/
public abstract <T> T executeAndExtract(Function function, Object... args);
/**
* Execute a function registered with an ID
* @param functionId the function ID
* @param args the calling arguments
* @return the results
*/
public abstract <T> Iterable<T> execute(String functionId, Object... args);
/**
* Execute a function registered with an ID and with an expected singleton result
* @param functionId the function ID
* @param args the calling arguments
* @return the first item in the results collector
*/
public abstract <T> T executeAndExtract(String functionId, Object... args);
/**
* Execute a function using a native GemFire {@link Execution} instance
* @param callback a callback providing the execution instance
* @return the execution result
*/
public abstract <T> T execute(GemfireFunctionCallback<T> callback);
}

View File

@@ -0,0 +1,178 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.execution;
import java.lang.reflect.Method;
import org.aopalliance.intercept.MethodInterceptor;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.aop.framework.ProxyFactory;
import org.springframework.aop.support.AopUtils;
import org.springframework.beans.factory.BeanClassLoaderAware;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.data.gemfire.function.config.FunctionId;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import com.gemstone.gemfire.cache.execute.FunctionException;
/**
* A proxy Factory Bean for all non-region function execution interfaces
*
* @author David Turanski
*
*/
public class GemfireFunctionProxyFactoryBean implements FactoryBean<Object>, MethodInterceptor, BeanClassLoaderAware, InitializingBean {
protected volatile ClassLoader beanClassLoader = ClassUtils.getDefaultClassLoader();
protected final Class<?> serviceInterface;
protected volatile Object serviceProxy;
private volatile boolean initialized;
protected String functionId;
protected Log logger = LogFactory.getLog(this.getClass());
protected final GemfireFunctionOperations gemfireFunctionOperations;
private FunctionExecutionMethodMetadata<MethodMetadata> methodMetadata;
/**
* @param serviceInterface the proxied interface
* @param functionId the associated function id (must be a function registered by this id with the GemFire {@link FunctionService}
* @param gemfireFunctionOperations an interface used to delegate the function invocation (typically a GemFire function template)
*/
public GemfireFunctionProxyFactoryBean(Class<?> serviceInterface,
GemfireFunctionOperations gemfireFunctionOperations) {
Assert.notNull(serviceInterface, "'serviceInterface' must not be null");
Assert.isTrue(serviceInterface.isInterface(), "'serviceInterface' must be an interface");
this.serviceInterface = serviceInterface;
this.gemfireFunctionOperations = gemfireFunctionOperations;
this.methodMetadata = new DefaultFunctionExecutionMethodMetadata(serviceInterface);
}
protected Iterable<?> invokeFunction(Method method, Object[] args) {
MethodMetadata mmd = this.methodMetadata.getMethodMetadata(method);
return this.gemfireFunctionOperations.execute(mmd.getFunctionId(), args);
}
@Override
public void setBeanClassLoader(ClassLoader classLoader) {
beanClassLoader = classLoader;
}
@Override
public Object invoke(MethodInvocation invocation) throws Throwable {
if (AopUtils.isToStringMethod(invocation.getMethod())) {
return "Gemfire function proxy for service interface [" + this.serviceInterface + "]";
}
if (logger.isDebugEnabled()) {
logger.debug("invoking method " + invocation.getMethod().getName());
}
Iterable<?> results = invokeFunction(invocation.getMethod(), invocation.getArguments());
return extractResult(results, invocation.getMethod().getReturnType());
}
@Override
public Object getObject() throws Exception {
if (this.serviceProxy == null) {
this.onInit();
Assert.notNull(this.serviceProxy, "failed to initialize proxy");
}
return this.serviceProxy;
}
@Override
public Class<?> getObjectType() {
return (this.serviceInterface != null ? this.serviceInterface : null);
}
@Override
public boolean isSingleton() {
return true;
}
protected void onInit() {
if (this.initialized) {
return;
}
ProxyFactory proxyFactory = new ProxyFactory(serviceInterface, this);
this.serviceProxy = proxyFactory.getProxy(this.beanClassLoader);
this.initialized = true;
}
protected String annotatedFunctionId(Method method) {
FunctionId functionIdAnnotation = method.getAnnotation(FunctionId.class);
return (functionIdAnnotation == null) ? null: functionIdAnnotation.value();
}
/**
* Optional to set a default function Id for a single method interface with no {code}@FunctionId{code} annotations
* @param functionId
*/
protected void setFunctionId(String functionId) {
this.functionId = functionId;
}
/*
* Match the result to the declared return type
*/
private Object extractResult(Iterable<?> results, Class<?> returnType) {
Object result = null;
if (results != null) {
if (Iterable.class.isAssignableFrom(returnType)) {
result = results;
} else {
int nonNullItems = 0;
for (Object obj : results) {
if (obj != null) {
if (++nonNullItems > 1) {
throw new FunctionException("multiple results found for single valued return type");
} else {
result = obj;
}
}
}
}
if (logger.isDebugEnabled()) {
logger.debug("returning result as " + result.getClass().getName());
}
}
return result;
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@Override
public void afterPropertiesSet() throws Exception {
if (this.functionId != null) {
Assert.isTrue(this.methodMetadata.isSingletonInterface(), "cannot assign default function id if interface has multiple methods");
this.methodMetadata.getSingletonMethodMetada().setFunctionId(this.functionId);
}
}
}

View File

@@ -0,0 +1,54 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.execution;
import com.gemstone.gemfire.distributed.DistributedMember;
/**
*
* @author David Turanski
*
*/
public class GemfireOnMemberFunctionTemplate extends AbstractFunctionTemplate {
private final DistributedMember distributedMember;
private final String[] groups;
public GemfireOnMemberFunctionTemplate (DistributedMember distributedMember) {
this.distributedMember = distributedMember;
this.groups = null;
}
public GemfireOnMemberFunctionTemplate (String[] groups) {
this.distributedMember = null;
this.groups = groups;
}
public GemfireOnMemberFunctionTemplate () {
this.distributedMember = null;
this.groups = null;
}
protected FunctionExecution getFunctionExecution() {
if (distributedMember == null && groups == null) {
return new DefaultMemberFunctionExecution();
} else if (distributedMember == null) {
return new GroupMemberFunctionExecution(this.groups);
}
return new DistributedMemberFunctionExecution(this.distributedMember);
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.execution;
import java.util.Set;
import com.gemstone.gemfire.distributed.DistributedMember;
/**
* @author David Turanski
*
*/
public class GemfireOnMembersFunctionTemplate extends AbstractFunctionTemplate {
private final Set<DistributedMember> distributedMembers;
private final String[] groups;
GemfireOnMembersFunctionTemplate (Set<DistributedMember> distributedMembers) {
this.distributedMembers = distributedMembers;
this.groups = null;
}
GemfireOnMembersFunctionTemplate (String[] groups) {
this.distributedMembers = null;
this.groups = groups;
}
GemfireOnMembersFunctionTemplate () {
this.distributedMembers = null;
this.groups = null;
}
protected FunctionExecution getFunctionExecution() {
if (distributedMembers == null && groups == null) {
return new AllMembersFunctionExecution();
} else if (distributedMembers == null) {
return new GroupMembersFunctionExecution(this.groups);
}
return new DistributedMembersFunctionExecution(this.distributedMembers);
}
}

View File

@@ -0,0 +1,73 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.execution;
import java.util.Set;
import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.Region;
import com.gemstone.gemfire.cache.execute.Function;
/**
* @author David Turanski
*
*/
public class GemfireOnRegionFunctionTemplate extends AbstractFunctionTemplate implements GemfireOnRegionOperations {
private Region<?, ?> region;
/**
*
* @param region
*/
public GemfireOnRegionFunctionTemplate(Region<?,?> region) {
Assert.notNull(region, "Region cannot be null");
this.region = region;
}
@Override
public <T> Iterable<T> execute(Function function, Set<?> keys, Object... args) {
return execute(new RegionFunctionExecution(region)
.setKeys(keys)
.setFunction(function)
.setTimeout(timeout)
.setArgs(args) );
}
@Override
public <T> Iterable<T> execute(String functionId, Set<?> keys, Object... args) {
return execute(new RegionFunctionExecution(region)
.setKeys(keys)
.setFunctionId(functionId)
.setTimeout(timeout)
.setArgs(args) );
}
@Override
public <T> T executeAndextract(String functionId, Set<?> keys, Object... args) {
return executeAndExtract(new RegionFunctionExecution(region)
.setKeys(keys)
.setFunctionId(functionId)
.setTimeout(timeout)
.setArgs(args) );
}
@Override
protected FunctionExecution getFunctionExecution() {
return new RegionFunctionExecution(this.region);
}
}

View File

@@ -0,0 +1,30 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.execution;
import java.util.Set;
import com.gemstone.gemfire.cache.execute.Function;
/**
* @author David Turanski
*
* @param <T>
*/
public interface GemfireOnRegionOperations extends GemfireFunctionOperations {
public abstract <T> Iterable<T> execute(String functionId, Set<?> keys, Object... args);
public abstract <T> Iterable<T> execute(Function function, Set<?> keys, Object... args);
public abstract <T> T executeAndextract(String functionId, Set<?> keys, Object... args);
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.execution;
import com.gemstone.gemfire.cache.RegionService;
import com.gemstone.gemfire.cache.client.Pool;
/**
* @author David Turanski
*
*/
public class GemfireOnServerFunctionTemplate extends AbstractFunctionTemplate {
private final RegionService cache;
private final Pool pool;
GemfireOnServerFunctionTemplate (RegionService cache) {
this.cache = cache;
this.pool = null;
}
GemfireOnServerFunctionTemplate (Pool pool) {
this.pool = pool;
this.cache = null;
}
@Override
protected FunctionExecution getFunctionExecution() {
if (this.pool == null) {
return new ServerFunctionExecution(this.cache);
}
return new PoolServerFunctionExecution(this.pool);
}
}

View File

@@ -0,0 +1,47 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.execution;
import com.gemstone.gemfire.cache.RegionService;
import com.gemstone.gemfire.cache.client.Pool;
/**
* @author David Turanski
*
*/
public class GemfireOnServersFunctionTemplate extends AbstractFunctionTemplate {
private final RegionService cache;
private final Pool pool;
GemfireOnServersFunctionTemplate (RegionService cache) {
this.cache = cache;
this.pool = null;
}
GemfireOnServersFunctionTemplate (Pool pool) {
this.pool = pool;
this.cache = null;
}
@Override
protected FunctionExecution getFunctionExecution() {
if (this.pool == null) {
return new ServersFunctionExecution(this.cache);
}
return new PoolServersFunctionExecution(this.pool);
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.execution;
import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.FunctionService;
/**
* @author David Turanski
*
*/
public class GroupMemberFunctionExecution extends FunctionExecution {
private final String groups[];
/**
*
* @param groups
*/
public GroupMemberFunctionExecution(String... groups) {
super();
Assert.notEmpty(groups, "groups cannot be null or empty.");
this.groups = groups;
}
@Override
protected Execution getExecution() {
return FunctionService.onMember(this.groups);
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.execution;
import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.FunctionService;
/**
* @author David Turanski
*
*/
public class GroupMembersFunctionExecution extends FunctionExecution {
private final String groups[];
/**
*
* @param groups
*/
public GroupMembersFunctionExecution(String... groups) {
super();
Assert.notEmpty(groups, "groups cannot be null or empty.");
this.groups = groups;
}
@Override
protected Execution getExecution() {
return FunctionService.onMember(this.groups);
}
}

View File

@@ -0,0 +1,58 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.execution;
import java.lang.reflect.Method;
import java.util.Set;
import org.springframework.data.gemfire.function.config.Filter;
import org.springframework.data.gemfire.function.config.GemfireFunctionUtils;
/**
* @author David Turanski
*
*/
class OnRegionExecutionMethodMetadata extends FunctionExecutionMethodMetadata<OnRegionMethodMetadata> {
/**
* @param serviceInterface
*/
public OnRegionExecutionMethodMetadata(Class<?> serviceInterface) {
super(serviceInterface);
}
/* (non-Javadoc)
* @see org.springframework.data.gemfire.function.config.FunctionExecutionMethodMetadata#newMetadataInstance(java.lang.reflect.Method)
*/
@Override
protected OnRegionMethodMetadata newMetadataInstance(Method method) {
return new OnRegionMethodMetadata(method);
}
}
class OnRegionMethodMetadata extends MethodMetadata {
private final int filterArgPosition;
public OnRegionMethodMetadata(Method method) {
super(method);
this.filterArgPosition = GemfireFunctionUtils.getAnnotationParameterPosition(method, Filter.class, new Class<?>[]{Set.class});
}
public int getFilterArgPosition() {
return this.filterArgPosition;
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.execution;
import java.lang.reflect.Method;
import java.util.Set;
import org.springframework.data.gemfire.util.ArrayUtils;
/**
* @author David Turanski
*
*/
public class OnRegionFunctionProxyFactoryBean extends GemfireFunctionProxyFactoryBean {
private OnRegionExecutionMethodMetadata methodMetadata;
/**
* @param serviceInterface
* @param gemfireOnRegionOperations an {@link GemfireOnRegionOperations} instance
*/
public OnRegionFunctionProxyFactoryBean(Class<?> serviceInterface,
GemfireOnRegionOperations gemfireOnRegionOperations) {
super(serviceInterface, (GemfireFunctionOperations) gemfireOnRegionOperations);
methodMetadata = new OnRegionExecutionMethodMetadata(serviceInterface);
}
@Override
protected Iterable<?> invokeFunction(Method method, Object[] args) {
Set<?> filter = null;
Iterable<?> results = null;
GemfireOnRegionOperations gemfireOnRegionOperations = (GemfireOnRegionOperations) this.gemfireFunctionOperations;
OnRegionMethodMetadata ormmd = methodMetadata.getMethodMetadata(method);
int filterArgPosition = ormmd.getFilterArgPosition();
String functionId = ormmd.getFunctionId();
/*
* extract filter from args if necessary
*/
if (filterArgPosition >=0 ) {
filter = (Set<?>)args[filterArgPosition];
args = ArrayUtils.remove(args, filterArgPosition);
}
if (filter == null) {
results = gemfireOnRegionOperations.execute(functionId, args);
} else {
results = gemfireOnRegionOperations.execute(functionId, filter, args);
}
return results;
}
}

View File

@@ -0,0 +1,68 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.execution;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.client.ClientCache;
import com.gemstone.gemfire.cache.client.Pool;
import com.gemstone.gemfire.cache.client.PoolManager;
import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.FunctionService;
/**
* Creates a GemFire {@link Execution} using {code}FunctionService.onServer(Pool pool){code}
* @author David Turanski
*
*/
public class PoolServerFunctionExecution extends FunctionExecution implements InitializingBean {
private Pool pool;
private String poolname;
/**
* @param pool the {@link Pool}
*/
public PoolServerFunctionExecution(Pool pool) {
super();
Assert.notNull(pool, "pool cannot be null");
this.pool = pool;
}
public PoolServerFunctionExecution(String poolname) {
super();
Assert.notNull(poolname, "pool name cannot be null");
this.poolname = poolname;
}
@Override
protected Execution getExecution() {
return FunctionService.onServer(this.pool);
}
/* (non-Javadoc)
* @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
*/
@Override
public void afterPropertiesSet() throws Exception {
this.pool = PoolManager.find(poolname);
Assert.notNull(pool," pool " + poolname+ " does not exist");
}
}

View File

@@ -0,0 +1,44 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.execution;
import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.client.Pool;
import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.FunctionService;
/**
* Creates a GemFire {@link Execution} using {code}FunctionService.onServers(Pool pool){code}
* @author David Turanski
*
*/
public class PoolServersFunctionExecution extends FunctionExecution {
private final Pool pool;
/**
* @param pool the {@link Pool}
*/
public PoolServersFunctionExecution(Pool pool ) {
super();
Assert.notNull(pool, "pool cannot be null");
this.pool = pool;
}
@Override
protected Execution getExecution() {
return FunctionService.onServers(this.pool);
}
}

View File

@@ -10,38 +10,35 @@
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* 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;
}
}

View File

@@ -0,0 +1,43 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.function.execution;
import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.RegionService;
import com.gemstone.gemfire.cache.execute.Execution;
import com.gemstone.gemfire.cache.execute.FunctionService;
/**
* Creates a GemFire {@link Execution} using {code}FunctionService.onServer(RegionService regionService){code}
* @author David Turanski
*
*/
public class ServerFunctionExecution extends FunctionExecution {
private RegionService regionService;
public ServerFunctionExecution(RegionService regionService) {
super();
Assert.notNull(regionService,"regionService cannot be null");
this.regionService = regionService;
}
@Override
protected Execution getExecution() {
return FunctionService.onServer(this.regionService);
}
}

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2002-2011 the original author or authors.
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* 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);

View File

@@ -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,

View File

@@ -0,0 +1,88 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.util;
/**
* @author David Turanski
*
*/
public abstract class ArrayUtils {
/**
* Insert an element into an array. The element is inserted at the
* given position, all elements afterwards are moved to the right.
*
* @param originalArray array to insert into
* @param pos position at which to insert the element
* @param element element to add
* @return the new array
*/
public static Object[] insert(Object[] originalArray, int pos, Object element) {
Object[] newArray = (Object[]) java.lang.reflect.Array.newInstance(
originalArray.getClass().getComponentType(), originalArray.length + 1);
// copy everything before the given position
if (pos > 0) {
System.arraycopy(originalArray, 0, newArray, 0, pos); // does not copy originalArray[pos], where we insert
}
// insert
newArray[pos] = element;
// copy remaining elements
if (pos < originalArray.length) {
System.arraycopy(originalArray, pos, // originalArray[pos] first element copied
newArray, pos + 1, // newArray[pos + 1] first destination
originalArray.length - pos); // number of elements left
}
return newArray;
}
/**
* Remove element from an array. The element is removed at the
* specified position, and all remaining elements are moved to the left.
*
* @param originalArray array to remove from
* @param pos position to remove
* @return the new array
*/
public static Object[] remove(Object[] originalArray, int pos) {
Object[] newArray = (Object[])java.lang.reflect.Array.newInstance(
originalArray.getClass().getComponentType(), originalArray.length - 1);
// Copy everything before
if (pos > 0) {
System.arraycopy(originalArray, 0, newArray, 0, pos); // originalArray[pos - 1] is last element copied
}
// Copy everything after
if (pos < originalArray.length - 1) {
System.arraycopy(originalArray, pos + 1, // originalArray[pos + 1] is first element copied
newArray, pos, // first position to copy into
originalArray.length - 1 - pos);
}
return newArray;
}
}

View File

@@ -34,15 +34,25 @@ public abstract class AbstractWANComponentFactoryBean<T> implements FactoryBean<
DisposableBean {
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();
}

View File

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

View File

@@ -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()) {

View File

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

View File

@@ -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;
}
}

View File

@@ -0,0 +1,277 @@
/*
* Copyright 2002-2012 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
* an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
* specific language governing permissions and limitations under the License.
*/
package org.springframework.data.gemfire.wan;
import java.util.List;
import org.springframework.context.SmartLifecycle;
import org.springframework.util.Assert;
import com.gemstone.gemfire.cache.util.Gateway.OrderPolicy;
import com.gemstone.gemfire.cache.wan.GatewayEventFilter;
import com.gemstone.gemfire.cache.wan.GatewaySender;
import com.gemstone.gemfire.cache.wan.GatewayTransportFilter;
/**
* A {@link GatewaySender} controlled by {@link SmartLifecycle}
* @author David Turanski
*
*/
public class SmartLifecycleGatewaySender implements GatewaySender, SmartLifecycle {
private final GatewaySender delegate;
private final boolean autoStartup;
public SmartLifecycleGatewaySender(GatewaySender delegate, boolean autoStartup) {
Assert.notNull(delegate);
this.delegate = delegate;
this.autoStartup = autoStartup;
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#addGatewayEventFilter(com.gemstone.gemfire.cache.wan.GatewayEventFilter)
*/
@Override
public void addGatewayEventFilter(GatewayEventFilter eventFilter) {
this.delegate.addGatewayEventFilter(eventFilter);
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#getAlertThreshold()
*/
@Override
public int getAlertThreshold() {
return this.delegate.getAlertThreshold();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#getBatchSize()
*/
@Override
public int getBatchSize() {
return this.delegate.getBatchSize();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#getBatchTimeInterval()
*/
@Override
public int getBatchTimeInterval() {
return this.delegate.getBatchTimeInterval();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#getDiskStoreName()
*/
@Override
public String getDiskStoreName() {
return this.delegate.getDiskStoreName();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#getDispatcherThreads()
*/
@Override
public int getDispatcherThreads() {
return this.delegate.getDispatcherThreads();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#getGatewayEventFilters()
*/
@Override
public List<GatewayEventFilter> getGatewayEventFilters() {
return this.delegate.getGatewayEventFilters();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#getGatewayTransportFilters()
*/
@Override
public List<GatewayTransportFilter> getGatewayTransportFilters() {
return this.delegate.getGatewayTransportFilters();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#getId()
*/
@Override
public String getId() {
return this.delegate.getId();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#getMaximumQueueMemory()
*/
@Override
public int getMaximumQueueMemory() {
return this.delegate.getMaximumQueueMemory();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#getOrderPolicy()
*/
@Override
public OrderPolicy getOrderPolicy() {
return this.delegate.getOrderPolicy();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#getRemoteDSId()
*/
@Override
public int getRemoteDSId() {
return this.delegate.getRemoteDSId();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#getSocketBufferSize()
*/
@Override
public int getSocketBufferSize() {
return this.delegate.getSocketBufferSize();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#getSocketReadTimeout()
*/
@Override
public int getSocketReadTimeout() {
return this.delegate.getSocketReadTimeout();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#isBatchConflationEnabled()
*/
@Override
public boolean isBatchConflationEnabled() {
return this.delegate.isBatchConflationEnabled();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#isDiskSynchronous()
*/
@Override
public boolean isDiskSynchronous() {
return this.delegate.isDiskSynchronous();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#isManualStart()
*/
@Override
public boolean isManualStart() {
return true;
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#isParallel()
*/
@Override
public boolean isParallel() {
return this.delegate.isParallel();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#isPaused()
*/
@Override
public boolean isPaused() {
return this.delegate.isPaused();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#isPersistenceEnabled()
*/
@Override
public boolean isPersistenceEnabled() {
return this.delegate.isPersistenceEnabled();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#isRunning()
*/
@Override
public boolean isRunning() {
return this.delegate.isRunning();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#pause()
*/
@Override
public void pause() {
this.delegate.pause();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#removeGatewayEventFilter(com.gemstone.gemfire.cache.wan.GatewayEventFilter)
*/
@Override
public void removeGatewayEventFilter(GatewayEventFilter eventFilter) {
this.delegate.removeGatewayEventFilter(eventFilter);
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#resume()
*/
@Override
public void resume() {
this.delegate.resume();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#start()
*/
@Override
public void start() {
this.delegate.start();
}
/* (non-Javadoc)
* @see com.gemstone.gemfire.cache.wan.GatewaySender#stop()
*/
@Override
public void stop() {
this.delegate.stop();
}
/* (non-Javadoc)
* @see org.springframework.context.Phased#getPhase()
*/
@Override
public int getPhase() {
return Integer.MAX_VALUE;
}
/* (non-Javadoc)
* @see org.springframework.context.SmartLifecycle#isAutoStartup()
*/
@Override
public boolean isAutoStartup() {
return this.autoStartup ;
}
/* (non-Javadoc)
* @see org.springframework.context.SmartLifecycle#stop(java.lang.Runnable)
*/
@Override
public void stop(Runnable callback) {
stop();
callback.run();
}
}