Added function-executions element to gfe-data namespace plus more cleanup
This commit is contained in:
@@ -17,6 +17,7 @@
|
|||||||
package org.springframework.data.gemfire.config;
|
package org.springframework.data.gemfire.config;
|
||||||
|
|
||||||
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
import org.springframework.beans.factory.xml.NamespaceHandlerSupport;
|
||||||
|
import org.springframework.data.gemfire.function.config.FunctionExecutionBeanDefinitionParser;
|
||||||
import org.springframework.data.gemfire.repository.config.GemfireRepositoryConfigurationExtension;
|
import org.springframework.data.gemfire.repository.config.GemfireRepositoryConfigurationExtension;
|
||||||
import org.springframework.data.repository.config.RepositoryBeanDefinitionParser;
|
import org.springframework.data.repository.config.RepositoryBeanDefinitionParser;
|
||||||
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
|
import org.springframework.data.repository.config.RepositoryConfigurationExtension;
|
||||||
@@ -35,5 +36,6 @@ class GemfireDataNamespaceHandler extends NamespaceHandlerSupport {
|
|||||||
// Repository namespace
|
// Repository namespace
|
||||||
RepositoryConfigurationExtension extension = new GemfireRepositoryConfigurationExtension();
|
RepositoryConfigurationExtension extension = new GemfireRepositoryConfigurationExtension();
|
||||||
registerBeanDefinitionParser("repositories", new RepositoryBeanDefinitionParser(extension));
|
registerBeanDefinitionParser("repositories", new RepositoryBeanDefinitionParser(extension));
|
||||||
|
registerBeanDefinitionParser("function-executions", new FunctionExecutionBeanDefinitionParser());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.io.Serializable;
|
|
||||||
import java.util.Set;
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @author David Turanski
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
public interface FilterAware {
|
|
||||||
/*
|
|
||||||
* Return calling instance to support method chaining
|
|
||||||
*/
|
|
||||||
public Object setFilter(Set<? extends Serializable> filter);
|
|
||||||
}
|
|
||||||
@@ -1,243 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.io.Serializable;
|
|
||||||
import java.lang.reflect.Constructor;
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
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.util.ClassUtils;
|
|
||||||
import org.springframework.util.ObjectUtils;
|
|
||||||
import org.springframework.util.ReflectionUtils;
|
|
||||||
|
|
||||||
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.FunctionException;
|
|
||||||
import com.gemstone.gemfire.cache.execute.RegionFunctionContext;
|
|
||||||
import com.gemstone.gemfire.cache.execute.ResultSender;
|
|
||||||
import com.gemstone.gemfire.cache.partition.PartitionRegionHelper;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 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.
|
|
||||||
* The delegate class must be the class path of the remote cache(s)
|
|
||||||
* @author David Turanski
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("serial")
|
|
||||||
public class MethodInvokingFunction implements Function {
|
|
||||||
public static final String FUNCTION_ID = MethodInvokingFunction.class.getName();
|
|
||||||
private static transient Log logger = LogFactory.getLog(MethodInvokingFunction.class);
|
|
||||||
|
|
||||||
private volatile boolean HA;
|
|
||||||
private volatile boolean optimizeForWrite;
|
|
||||||
private volatile boolean hasResult;
|
|
||||||
private String id;
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public MethodInvokingFunction( ) {
|
|
||||||
this.HA = false;
|
|
||||||
this.hasResult = true;
|
|
||||||
this.optimizeForWrite = false;
|
|
||||||
this.id = FUNCTION_ID;
|
|
||||||
}
|
|
||||||
|
|
||||||
//@Override
|
|
||||||
public String getId() {
|
|
||||||
return this.id;
|
|
||||||
}
|
|
||||||
|
|
||||||
//@Override
|
|
||||||
public boolean hasResult() {
|
|
||||||
return hasResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHasResult(boolean hasResult) {
|
|
||||||
this.hasResult = hasResult;
|
|
||||||
}
|
|
||||||
|
|
||||||
//@Override
|
|
||||||
public boolean isHA() {
|
|
||||||
return HA;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setHA(boolean HA) {
|
|
||||||
this.HA = HA;
|
|
||||||
}
|
|
||||||
|
|
||||||
public void setId(String id) {
|
|
||||||
this.id = id;
|
|
||||||
}
|
|
||||||
|
|
||||||
//@Override
|
|
||||||
public boolean optimizeForWrite() {
|
|
||||||
return optimizeForWrite;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public void setOptimizeForWrite(boolean optimizeForWrite) {
|
|
||||||
this.optimizeForWrite = optimizeForWrite;
|
|
||||||
}
|
|
||||||
|
|
||||||
//@Override
|
|
||||||
public void execute(FunctionContext functionContext) {
|
|
||||||
Region<?,?> region = null;
|
|
||||||
RegionFunctionContext regionFunctionContext = (RegionFunctionContext)functionContext;
|
|
||||||
|
|
||||||
region = getRegionForContext(regionFunctionContext);
|
|
||||||
|
|
||||||
RemoteMethodInvocation invocation = null;
|
|
||||||
|
|
||||||
if (regionFunctionContext.getArguments().getClass().isArray()) {
|
|
||||||
invocation = (RemoteMethodInvocation)((Serializable[])regionFunctionContext.getArguments())[0];
|
|
||||||
} else {
|
|
||||||
invocation = (RemoteMethodInvocation)regionFunctionContext.getArguments();
|
|
||||||
}
|
|
||||||
|
|
||||||
regionFunctionContext.getFilter();
|
|
||||||
|
|
||||||
Object instance = createDelegateInstance(invocation.getClassName(), region);
|
|
||||||
|
|
||||||
Serializable result = invokeDelegateMethod(instance,invocation, region);
|
|
||||||
|
|
||||||
if (hasResult()){
|
|
||||||
sendResults(regionFunctionContext.getResultSender(),result);
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
protected final Serializable invokeDelegateMethod(Object instance, RemoteMethodInvocation invocation, Region<?,?> region) {
|
|
||||||
|
|
||||||
|
|
||||||
// Null parameters returns any method signature
|
|
||||||
Method method = ReflectionUtils.findMethod(instance.getClass(),invocation.getMethodName(),(Class<?>[])null);
|
|
||||||
|
|
||||||
if (method == null ) {
|
|
||||||
throw new FunctionException("cannot find method ["+ invocation.getMethodName() +
|
|
||||||
"] on type [" + instance.getClass().getName() + "]");
|
|
||||||
}
|
|
||||||
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug(String.format("about to invoke method %s on class %s", invocation.getMethodName(),invocation.getClassName()));
|
|
||||||
for (Object arg: invocation.getArguments()) {
|
|
||||||
logger.debug("arg:"+ arg.getClass().getName() + " " + arg.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
return (Serializable)ReflectionUtils.invokeMethod(method, instance, (Object[]) invocation.getArguments());
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
protected final Object createDelegateInstance(String delegateClassName, Map<?,?> region) {
|
|
||||||
Object instance = null;
|
|
||||||
try {
|
|
||||||
Class<?> clazz = Class.forName(delegateClassName);
|
|
||||||
Constructor<?> defaultConstructor = ClassUtils.getConstructorIfAvailable(clazz, new Class<?>[] {});
|
|
||||||
if (region != null){
|
|
||||||
Constructor<?> mapConstructor = ClassUtils.getConstructorIfAvailable(clazz, Map.class);
|
|
||||||
if (mapConstructor != null){
|
|
||||||
instance = mapConstructor.newInstance(region);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (instance == null) {
|
|
||||||
if (defaultConstructor == null) {
|
|
||||||
throw new FunctionException("Delegate type [" + delegateClassName + "] has no default constructor");
|
|
||||||
}
|
|
||||||
instance = defaultConstructor.newInstance();
|
|
||||||
}
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
logger.error(e.getMessage(),e);
|
|
||||||
throw new FunctionException("Delegate type [" + delegateClassName + "] not found", e);
|
|
||||||
} catch (SecurityException e) {
|
|
||||||
logger.error(e.getMessage(),e);
|
|
||||||
throw new FunctionException(e);
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
logger.error(e.getMessage(),e);
|
|
||||||
throw new FunctionException("Delegate constructor failed",e);
|
|
||||||
} catch (InstantiationException e) {
|
|
||||||
logger.error(e.getMessage(),e);
|
|
||||||
throw new FunctionException("Delegate constructor failed",e);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
logger.error(e.getMessage(),e);
|
|
||||||
throw new FunctionException("Delegate constructor failed",e);
|
|
||||||
} catch (InvocationTargetException e) {
|
|
||||||
logger.error(e.getMessage(),e);
|
|
||||||
throw new FunctionException("Delegate constructor failed",e);
|
|
||||||
} catch (Throwable t){
|
|
||||||
logger.error(t.getMessage(),t);
|
|
||||||
throw new FunctionException("Delegate constructor failed",t);
|
|
||||||
}
|
|
||||||
return instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* @param regionFunctionContext
|
|
||||||
* @return
|
|
||||||
*/
|
|
||||||
private Region<?, ?> getRegionForContext(RegionFunctionContext regionFunctionContext) {
|
|
||||||
|
|
||||||
Region<?,?> region = regionFunctionContext.getDataSet();
|
|
||||||
if (PartitionRegionHelper.isPartitionedRegion(region)) {
|
|
||||||
if (logger.isDebugEnabled()){
|
|
||||||
logger.debug("this is a partitioned region - filtering local data for context");
|
|
||||||
}
|
|
||||||
region = PartitionRegionHelper.getLocalDataForContext(regionFunctionContext);
|
|
||||||
}
|
|
||||||
if (logger.isDebugEnabled()){
|
|
||||||
logger.debug("region contains " + region.size() + " items");
|
|
||||||
}
|
|
||||||
return region;
|
|
||||||
}
|
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
private void sendResults(ResultSender<Object> resultSender, Serializable result) {
|
|
||||||
if (result == null){
|
|
||||||
resultSender.lastResult(null);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
Serializable lastItem = result;
|
|
||||||
|
|
||||||
List<Serializable> results = null;
|
|
||||||
if (ObjectUtils.isArray(result)){
|
|
||||||
results = Arrays.asList((Serializable[])result);
|
|
||||||
} else if (List.class.isAssignableFrom(result.getClass())) {
|
|
||||||
results = (List<Serializable>)result;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (results != null){
|
|
||||||
int i = 0;
|
|
||||||
for (Serializable item: results){
|
|
||||||
if (i++ < results.size() - 1) {
|
|
||||||
resultSender.sendResult(item);
|
|
||||||
} else {
|
|
||||||
lastItem = item;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
resultSender.lastResult(lastItem);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@@ -1,60 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.io.Serializable;
|
|
||||||
|
|
||||||
import org.springframework.util.Assert;
|
|
||||||
import org.springframework.util.StringUtils;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @author David Turanski
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
@SuppressWarnings("serial")
|
|
||||||
public class RemoteMethodInvocation implements Serializable {
|
|
||||||
private final String methodName;
|
|
||||||
private String className;
|
|
||||||
private final Serializable[] arguments;
|
|
||||||
|
|
||||||
public RemoteMethodInvocation(Class<?> clazz, String methodName, Serializable... args) {
|
|
||||||
this(methodName,args);
|
|
||||||
Assert.notNull(clazz , "class cannot be null");
|
|
||||||
this.className = clazz.getName();
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
public RemoteMethodInvocation(String className, String methodName, Serializable... args) {
|
|
||||||
this(methodName,args);
|
|
||||||
Assert.isTrue(StringUtils.hasLength(className.trim()) , "class cannot be null or empty");
|
|
||||||
this.className = className;
|
|
||||||
}
|
|
||||||
|
|
||||||
private RemoteMethodInvocation(String methodName, Serializable... args){
|
|
||||||
Assert.isTrue(StringUtils.hasLength(methodName.trim()), "methodName cannot be null or empty");
|
|
||||||
Assert.isTrue(StringUtils.hasLength(methodName.trim()), "methodName cannot be null or empty");
|
|
||||||
this.methodName = methodName;
|
|
||||||
this.arguments = args == null ? new Serializable[]{} : args;
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getMethodName() {
|
|
||||||
return methodName;
|
|
||||||
}
|
|
||||||
public String getClassName() {
|
|
||||||
return className;
|
|
||||||
}
|
|
||||||
public Serializable[] getArguments() {
|
|
||||||
return arguments;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* 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.Collection;
|
||||||
|
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.config.BeanDefinition;
|
||||||
|
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||||
|
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
|
||||||
|
import org.springframework.core.io.ResourceLoader;
|
||||||
|
import org.springframework.core.type.filter.TypeFilter;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Annotation based configuration source for function executions
|
||||||
|
*
|
||||||
|
* @author David Turanski
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
abstract class AbstractFunctionExecutionConfigurationSource implements FunctionExecutionConfigurationSource {
|
||||||
|
protected Log logger = LogFactory.getLog(this.getClass());
|
||||||
|
|
||||||
|
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static Set<Class<? extends Annotation>> getFunctionExecutionAnnotationTypes() {
|
||||||
|
return functionExecutionAnnotationTypes;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
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()) {
|
||||||
|
if (logger.isDebugEnabled()) {
|
||||||
|
logger.debug("scanning package " + basePackage);
|
||||||
|
}
|
||||||
|
Collection<BeanDefinition> components = scanner.findCandidateComponents(basePackage);
|
||||||
|
for (BeanDefinition definition : components) {
|
||||||
|
result.add((ScannedGenericBeanDefinition)definition);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -15,21 +15,14 @@ package org.springframework.data.gemfire.function.config;
|
|||||||
import java.lang.annotation.Annotation;
|
import java.lang.annotation.Annotation;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collection;
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
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.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.FilterType;
|
||||||
import org.springframework.context.annotation.ScannedGenericBeanDefinition;
|
|
||||||
import org.springframework.core.annotation.AnnotationAttributes;
|
import org.springframework.core.annotation.AnnotationAttributes;
|
||||||
import org.springframework.core.io.ResourceLoader;
|
|
||||||
import org.springframework.core.type.AnnotationMetadata;
|
import org.springframework.core.type.AnnotationMetadata;
|
||||||
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||||
import org.springframework.core.type.filter.AssignableTypeFilter;
|
import org.springframework.core.type.filter.AssignableTypeFilter;
|
||||||
@@ -43,25 +36,14 @@ import org.springframework.util.ClassUtils;
|
|||||||
* @author David Turanski
|
* @author David Turanski
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
class AnnotationFunctionExecutionConfigurationSource implements FunctionExecutionConfigurationSource {
|
class AnnotationFunctionExecutionConfigurationSource extends AbstractFunctionExecutionConfigurationSource {
|
||||||
private static Log logger = LogFactory.getLog(AnnotationFunctionExecutionConfigurationSource.class);
|
|
||||||
|
|
||||||
private static final String BASE_PACKAGES = "basePackages";
|
private static final String BASE_PACKAGES = "basePackages";
|
||||||
private static final String BASE_PACKAGE_CLASSES = "basePackageClasses";
|
private static final String BASE_PACKAGE_CLASSES = "basePackageClasses";
|
||||||
|
|
||||||
private final AnnotationMetadata metadata;
|
private final AnnotationMetadata metadata;
|
||||||
private final AnnotationAttributes attributes;
|
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
|
* Creates a new {@link AnnotationFunctionExecutionConfigurationSource} from the given {@link AnnotationMetadata} and
|
||||||
@@ -87,13 +69,7 @@ class AnnotationFunctionExecutionConfigurationSource implements FunctionExecutio
|
|||||||
public Object getSource() {
|
public Object getSource() {
|
||||||
// TODO Auto-generated method stub
|
// TODO Auto-generated method stub
|
||||||
return this.metadata;
|
return this.metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Set<Class<? extends Annotation>> getFunctionExecutionAnnotationTypes() {
|
|
||||||
return functionExecutionAnnotationTypes;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.springframework.data.gemfire.function.config.FunctionExecutionConfigurationSource#getBasePackages()
|
* @see org.springframework.data.gemfire.function.config.FunctionExecutionConfigurationSource#getBasePackages()
|
||||||
@@ -121,37 +97,14 @@ class AnnotationFunctionExecutionConfigurationSource implements FunctionExecutio
|
|||||||
return packages;
|
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()) {
|
|
||||||
if (logger.isDebugEnabled()) {
|
|
||||||
logger.debug("scanning package " + basePackage);
|
|
||||||
}
|
|
||||||
Collection<BeanDefinition> components = scanner.findCandidateComponents(basePackage);
|
|
||||||
for (BeanDefinition definition : components) {
|
|
||||||
result.add((ScannedGenericBeanDefinition)definition);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return result;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@Override
|
||||||
protected Iterable<TypeFilter> getIncludeFilters() {
|
public Iterable<TypeFilter> getIncludeFilters() {
|
||||||
return parseFilters("includeFilters");
|
return parseFilters("includeFilters");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
protected Iterable<TypeFilter> getExcludeFilters() {
|
public Iterable<TypeFilter> getExcludeFilters() {
|
||||||
return parseFilters("excludeFilters");
|
return parseFilters("excludeFilters");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* 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.config.BeanDefinition;
|
||||||
|
import org.springframework.beans.factory.xml.BeanDefinitionParser;
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author David Turanski
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
public class FunctionExecutionBeanDefinitionParser implements BeanDefinitionParser {
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.springframework.beans.factory.xml.BeanDefinitionParser#parse(org.w3c.dom.Element, org.springframework.beans.factory.xml.ParserContext)
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public BeanDefinition parse(Element element, ParserContext parserContext) {
|
||||||
|
|
||||||
|
AbstractFunctionExecutionConfigurationSource configurationSource =
|
||||||
|
new XmlFunctionExecutionConfigurationSource(element, parserContext);
|
||||||
|
new FunctionExecutionBeanDefinitionRegistrar().registerBeanDefinitions(configurationSource, parserContext.getRegistry());
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -15,8 +15,6 @@ package org.springframework.data.gemfire.function.config;
|
|||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
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.BeanDefinitionReaderUtils;
|
||||||
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
|
||||||
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
|
||||||
@@ -34,21 +32,27 @@ import org.springframework.util.StringUtils;
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public class FunctionExecutionBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
|
public class FunctionExecutionBeanDefinitionRegistrar implements ImportBeanDefinitionRegistrar {
|
||||||
|
|
||||||
private static Log logger = LogFactory.getLog(FunctionExecutionBeanDefinitionRegistrar.class);
|
|
||||||
/* (non-Javadoc)
|
/* (non-Javadoc)
|
||||||
* @see org.springframework.context.annotation.ImportBeanDefinitionRegistrar#registerBeanDefinitions(org.springframework.core.type.AnnotationMetadata, org.springframework.beans.factory.support.BeanDefinitionRegistry)
|
* @see org.springframework.context.annotation.ImportBeanDefinitionRegistrar#registerBeanDefinitions(org.springframework.core.type.AnnotationMetadata, org.springframework.beans.factory.support.BeanDefinitionRegistry)
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {
|
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry registry) {
|
||||||
|
AbstractFunctionExecutionConfigurationSource configurationSource = new AnnotationFunctionExecutionConfigurationSource(
|
||||||
ResourceLoader resourceLoader = new DefaultResourceLoader();
|
|
||||||
AnnotationFunctionExecutionConfigurationSource configurationSource = new AnnotationFunctionExecutionConfigurationSource(
|
|
||||||
annotationMetadata);
|
annotationMetadata);
|
||||||
|
|
||||||
|
registerBeanDefinitions(configurationSource, registry);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This registers bean definitions from any function execution configuration source
|
||||||
|
*/
|
||||||
|
void registerBeanDefinitions (AbstractFunctionExecutionConfigurationSource configurationSource, BeanDefinitionRegistry registry) {
|
||||||
|
ResourceLoader resourceLoader = new DefaultResourceLoader();
|
||||||
Set<String> functionExecutionAnnotationTypes = new HashSet<String>(
|
Set<String> functionExecutionAnnotationTypes = new HashSet<String>(
|
||||||
AnnotationFunctionExecutionConfigurationSource.getFunctionExecutionAnnotationTypes().size());
|
AnnotationFunctionExecutionConfigurationSource.getFunctionExecutionAnnotationTypes().size());
|
||||||
for (Class<?> annotation : AnnotationFunctionExecutionConfigurationSource.getFunctionExecutionAnnotationTypes()) {
|
for (Class<?> annotation : AbstractFunctionExecutionConfigurationSource.getFunctionExecutionAnnotationTypes()) {
|
||||||
functionExecutionAnnotationTypes.add(annotation.getName());
|
functionExecutionAnnotationTypes.add(annotation.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -70,7 +74,6 @@ public class FunctionExecutionBeanDefinitionRegistrar implements ImportBeanDefin
|
|||||||
|
|
||||||
registry.registerBeanDefinition(beanName, builder.build(registry));
|
registry.registerBeanDefinition(beanName, builder.build(registry));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private String getFunctionExecutionAnnotation(ScannedGenericBeanDefinition beanDefinition,
|
private String getFunctionExecutionAnnotation(ScannedGenericBeanDefinition beanDefinition,
|
||||||
@@ -91,4 +94,5 @@ public class FunctionExecutionBeanDefinitionRegistrar implements ImportBeanDefin
|
|||||||
|
|
||||||
return functionExecutionAnnotation;
|
return functionExecutionAnnotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -12,10 +12,7 @@
|
|||||||
*/
|
*/
|
||||||
package org.springframework.data.gemfire.function.config;
|
package org.springframework.data.gemfire.function.config;
|
||||||
|
|
||||||
import java.util.Collection;
|
import org.springframework.core.type.filter.TypeFilter;
|
||||||
|
|
||||||
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
|
* Interface for function execution configuration sources (e.g., annotation or XML configuration) to configure
|
||||||
@@ -40,11 +37,17 @@ interface FunctionExecutionConfigurationSource {
|
|||||||
*/
|
*/
|
||||||
Iterable<String> getBasePackages();
|
Iterable<String> getBasePackages();
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the scanned bean definitions
|
* Returns configured {@link TypeFilter}s
|
||||||
*
|
* @return include filters
|
||||||
* @param loader
|
|
||||||
* @return
|
|
||||||
*/
|
*/
|
||||||
Collection<ScannedGenericBeanDefinition> getCandidates(ResourceLoader loader);
|
Iterable<TypeFilter> getIncludeFilters();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns configured {@link TypeFilter}s
|
||||||
|
* @return exclude filters
|
||||||
|
*/
|
||||||
|
Iterable<TypeFilter> getExcludeFilters();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,232 @@
|
|||||||
|
/*
|
||||||
|
* 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.function.config;
|
||||||
|
|
||||||
|
import java.lang.annotation.Annotation;
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
import org.springframework.beans.BeanUtils;
|
||||||
|
import org.springframework.beans.FatalBeanException;
|
||||||
|
import org.springframework.beans.factory.parsing.ReaderContext;
|
||||||
|
import org.springframework.beans.factory.xml.XmlReaderContext;
|
||||||
|
import org.springframework.context.annotation.ClassPathScanningCandidateComponentProvider;
|
||||||
|
import org.springframework.core.type.filter.AnnotationTypeFilter;
|
||||||
|
import org.springframework.core.type.filter.AspectJTypeFilter;
|
||||||
|
import org.springframework.core.type.filter.AssignableTypeFilter;
|
||||||
|
import org.springframework.core.type.filter.RegexPatternTypeFilter;
|
||||||
|
import org.springframework.core.type.filter.TypeFilter;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
import org.w3c.dom.Node;
|
||||||
|
import org.w3c.dom.NodeList;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Parser to populate the given {@link ClassPathScanningCandidateComponentProvider} with {@link TypeFilter}s parsed from
|
||||||
|
* the given {@link Element}'s children.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
*/
|
||||||
|
class TypeFilterParser {
|
||||||
|
|
||||||
|
private static final String FILTER_TYPE_ATTRIBUTE = "type";
|
||||||
|
private static final String FILTER_EXPRESSION_ATTRIBUTE = "expression";
|
||||||
|
|
||||||
|
private final ReaderContext readerContext;
|
||||||
|
private final ClassLoader classLoader;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a new {@link TypeFilterParser} with the given {@link ReaderContext}.
|
||||||
|
*
|
||||||
|
* @param readerContext must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
public TypeFilterParser(XmlReaderContext readerContext) {
|
||||||
|
this(readerContext, readerContext.getResourceLoader().getClassLoader());
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Constructor to ease testing as {@link XmlReaderContext#getBeanClassLoader()} is final and thus cannot be mocked
|
||||||
|
* easily.
|
||||||
|
*
|
||||||
|
* @param readerContext must not be {@literal null}.
|
||||||
|
* @param classLoader must not be {@literal null}.
|
||||||
|
*/
|
||||||
|
TypeFilterParser(ReaderContext readerContext, ClassLoader classLoader) {
|
||||||
|
|
||||||
|
Assert.notNull(readerContext, "ReaderContext must not be null!");
|
||||||
|
Assert.notNull(classLoader, "ClassLoader must not be null!");
|
||||||
|
|
||||||
|
this.readerContext = readerContext;
|
||||||
|
this.classLoader = classLoader;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Iterable<TypeFilter> parseTypeFilters(Element element, Type type) {
|
||||||
|
|
||||||
|
NodeList nodeList = element.getChildNodes();
|
||||||
|
Collection<TypeFilter> filters = new HashSet<TypeFilter>();
|
||||||
|
|
||||||
|
for (int i = 0; i < nodeList.getLength(); i++) {
|
||||||
|
|
||||||
|
Node node = nodeList.item(i);
|
||||||
|
Element childElement = type.getElement(node);
|
||||||
|
|
||||||
|
if (childElement != null) {
|
||||||
|
|
||||||
|
try {
|
||||||
|
filters.add(createTypeFilter(childElement, classLoader));
|
||||||
|
} catch (RuntimeException e) {
|
||||||
|
readerContext.error(e.getMessage(), readerContext.extractSource(element), e.getCause());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return filters;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected TypeFilter createTypeFilter(Element element, ClassLoader classLoader) {
|
||||||
|
|
||||||
|
String filterType = element.getAttribute(FILTER_TYPE_ATTRIBUTE);
|
||||||
|
String expression = element.getAttribute(FILTER_EXPRESSION_ATTRIBUTE);
|
||||||
|
|
||||||
|
try {
|
||||||
|
|
||||||
|
FilterType filter = FilterType.fromString(filterType);
|
||||||
|
return filter.getFilter(expression, classLoader);
|
||||||
|
|
||||||
|
} catch (ClassNotFoundException ex) {
|
||||||
|
throw new FatalBeanException("Type filter class not found: " + expression, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Enum representing all the filter types available for {@code include} and {@code exclude} elements. This acts as
|
||||||
|
* factory for {@link TypeFilter} instances.
|
||||||
|
*
|
||||||
|
* @author Oliver Gierke
|
||||||
|
* @see #getFilter(String, ClassLoader)
|
||||||
|
*/
|
||||||
|
private static enum FilterType {
|
||||||
|
|
||||||
|
ANNOTATION {
|
||||||
|
@Override
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
public TypeFilter getFilter(String expression, ClassLoader classLoader) throws ClassNotFoundException {
|
||||||
|
|
||||||
|
return new AnnotationTypeFilter((Class<Annotation>) classLoader.loadClass(expression));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
ASSIGNABLE {
|
||||||
|
@Override
|
||||||
|
public TypeFilter getFilter(String expression, ClassLoader classLoader) throws ClassNotFoundException {
|
||||||
|
|
||||||
|
return new AssignableTypeFilter(classLoader.loadClass(expression));
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
ASPECTJ {
|
||||||
|
@Override
|
||||||
|
public TypeFilter getFilter(String expression, ClassLoader classLoader) {
|
||||||
|
|
||||||
|
return new AspectJTypeFilter(expression, classLoader);
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
REGEX {
|
||||||
|
@Override
|
||||||
|
public TypeFilter getFilter(String expression, ClassLoader classLoader) {
|
||||||
|
|
||||||
|
return new RegexPatternTypeFilter(Pattern.compile(expression));
|
||||||
|
}
|
||||||
|
|
||||||
|
},
|
||||||
|
|
||||||
|
CUSTOM {
|
||||||
|
@Override
|
||||||
|
public TypeFilter getFilter(String expression, ClassLoader classLoader) throws ClassNotFoundException {
|
||||||
|
|
||||||
|
Class<?> filterClass = classLoader.loadClass(expression);
|
||||||
|
if (!TypeFilter.class.isAssignableFrom(filterClass)) {
|
||||||
|
throw new IllegalArgumentException("Class is not assignable to [" + TypeFilter.class.getName() + "]: "
|
||||||
|
+ expression);
|
||||||
|
}
|
||||||
|
return (TypeFilter) BeanUtils.instantiateClass(filterClass);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link TypeFilter} for the given expression and {@link ClassLoader}.
|
||||||
|
*
|
||||||
|
* @param expression
|
||||||
|
* @param classLoader
|
||||||
|
* @return
|
||||||
|
* @throws ClassNotFoundException
|
||||||
|
*/
|
||||||
|
abstract TypeFilter getFilter(String expression, ClassLoader classLoader) throws ClassNotFoundException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link FilterType} for the given type as {@link String}.
|
||||||
|
*
|
||||||
|
* @param typeString
|
||||||
|
* @return
|
||||||
|
* @throws IllegalArgumentException if no {@link FilterType} could be found for the given argument.
|
||||||
|
*/
|
||||||
|
static FilterType fromString(String typeString) {
|
||||||
|
|
||||||
|
for (FilterType filter : FilterType.values()) {
|
||||||
|
if (filter.name().equalsIgnoreCase(typeString)) {
|
||||||
|
return filter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalArgumentException("Unsupported filter type: " + typeString);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static enum Type {
|
||||||
|
|
||||||
|
INCLUDE("include-filter"), EXCLUDE("exclude-filter");
|
||||||
|
|
||||||
|
private String elementName;
|
||||||
|
|
||||||
|
private Type(String elementName) {
|
||||||
|
|
||||||
|
this.elementName = elementName;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the {@link Element} if the given {@link Node} is an {@link Element} and it's name equals the one of the
|
||||||
|
* type.
|
||||||
|
*
|
||||||
|
* @param node
|
||||||
|
* @return
|
||||||
|
*/
|
||||||
|
Element getElement(Node node) {
|
||||||
|
|
||||||
|
if (node.getNodeType() == Node.ELEMENT_NODE) {
|
||||||
|
String localName = node.getLocalName();
|
||||||
|
if (elementName.equals(localName)) {
|
||||||
|
return (Element) node;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,81 @@
|
|||||||
|
/*
|
||||||
|
* 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.Arrays;
|
||||||
|
|
||||||
|
import org.springframework.beans.factory.xml.ParserContext;
|
||||||
|
import org.springframework.core.type.filter.TypeFilter;
|
||||||
|
import org.springframework.data.gemfire.function.config.TypeFilterParser.Type;
|
||||||
|
import org.springframework.util.Assert;
|
||||||
|
import org.springframework.util.StringUtils;
|
||||||
|
import org.w3c.dom.Element;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author David Turanski
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class XmlFunctionExecutionConfigurationSource extends AbstractFunctionExecutionConfigurationSource {
|
||||||
|
private static final String BASE_PACKAGE = "base-package";
|
||||||
|
private Element element;
|
||||||
|
private ParserContext context;
|
||||||
|
private Iterable<TypeFilter> includeFilters;
|
||||||
|
private Iterable<TypeFilter> excludeFilters;
|
||||||
|
|
||||||
|
XmlFunctionExecutionConfigurationSource(Element element, ParserContext context) {
|
||||||
|
Assert.notNull(element);
|
||||||
|
Assert.notNull(context);
|
||||||
|
|
||||||
|
this.element = element;
|
||||||
|
this.context = context;
|
||||||
|
|
||||||
|
TypeFilterParser parser = new TypeFilterParser(context.getReaderContext());
|
||||||
|
this.includeFilters = parser.parseTypeFilters(element, Type.INCLUDE);
|
||||||
|
this.excludeFilters = parser.parseTypeFilters(element, Type.EXCLUDE);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.gemfire.function.config.FunctionExecutionConfigurationSource#getSource()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Object getSource() {
|
||||||
|
return context.extractSource(element);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.gemfire.function.config.FunctionExecutionConfigurationSource#getBasePackages()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Iterable<String> getBasePackages() {
|
||||||
|
String attribute = element.getAttribute(BASE_PACKAGE);
|
||||||
|
return Arrays.asList(StringUtils.delimitedListToStringArray(attribute, ",", " "));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.gemfire.function.config.FunctionExecutionConfigurationSource#getIncludeFilters()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Iterable<TypeFilter> getIncludeFilters() {
|
||||||
|
return includeFilters;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* (non-Javadoc)
|
||||||
|
* @see org.springframework.data.gemfire.function.config.FunctionExecutionConfigurationSource#getExcludeFilters()
|
||||||
|
*/
|
||||||
|
@Override
|
||||||
|
public Iterable<TypeFilter> getExcludeFilters() {
|
||||||
|
return excludeFilters;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -31,7 +31,14 @@ targetNamespace="http://www.springframework.org/schema/data/gemfire" elementForm
|
|||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
</xsd:element>
|
</xsd:element>
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<xsd:complexType name="functions">
|
<xsd:element name="function-executions">
|
||||||
|
<xsd:annotation>
|
||||||
|
<xsd:documentation><![CDATA[
|
||||||
|
Enables component scanning for annotated function execution interfaces.
|
||||||
|
]]></xsd:documentation>
|
||||||
|
</xsd:annotation>
|
||||||
|
|
||||||
|
<xsd:complexType>
|
||||||
<xsd:sequence>
|
<xsd:sequence>
|
||||||
<xsd:element name="include-filter" type="context:filterType" minOccurs="0" maxOccurs="unbounded">
|
<xsd:element name="include-filter" type="context:filterType" minOccurs="0" maxOccurs="unbounded">
|
||||||
<xsd:annotation>
|
<xsd:annotation>
|
||||||
@@ -55,7 +62,8 @@ targetNamespace="http://www.springframework.org/schema/data/gemfire" elementForm
|
|||||||
]]></xsd:documentation>
|
]]></xsd:documentation>
|
||||||
</xsd:annotation>
|
</xsd:annotation>
|
||||||
</xsd:attribute>
|
</xsd:attribute>
|
||||||
</xsd:complexType>
|
</xsd:complexType>
|
||||||
|
</xsd:element>
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<xsd:attributeGroup name="gemfire-repository-attributes">
|
<xsd:attributeGroup name="gemfire-repository-attributes">
|
||||||
<xsd:attribute name="mapping-context-ref" type="mappingContextRef">
|
<xsd:attribute name="mapping-context-ref" type="mappingContextRef">
|
||||||
|
|||||||
@@ -18,13 +18,8 @@ import org.junit.Test;
|
|||||||
import org.junit.runner.RunWith;
|
import org.junit.runner.RunWith;
|
||||||
import org.springframework.beans.factory.annotation.Autowired;
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
import org.springframework.context.ApplicationContext;
|
import org.springframework.context.ApplicationContext;
|
||||||
import org.springframework.context.annotation.ComponentScan;
|
|
||||||
import org.springframework.context.annotation.Configuration;
|
import org.springframework.context.annotation.Configuration;
|
||||||
import org.springframework.context.annotation.FilterType;
|
|
||||||
import org.springframework.context.annotation.ImportResource;
|
import org.springframework.context.annotation.ImportResource;
|
||||||
import org.springframework.data.gemfire.function.config.EnableGemfireFunctionExecutions;
|
|
||||||
import org.springframework.data.gemfire.function.execution.GemfireFunctionProxyFactoryBean;
|
|
||||||
import org.springframework.data.gemfire.function.execution.OnRegionFunctionProxyFactoryBean;
|
|
||||||
import org.springframework.test.context.ContextConfiguration;
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* 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 static org.junit.Assert.assertEquals;
|
||||||
|
import static org.junit.Assert.assertSame;
|
||||||
|
|
||||||
|
import org.junit.Test;
|
||||||
|
import org.junit.runner.RunWith;
|
||||||
|
import org.springframework.beans.factory.annotation.Autowired;
|
||||||
|
import org.springframework.context.ApplicationContext;
|
||||||
|
import org.springframework.data.gemfire.TestUtils;
|
||||||
|
import org.springframework.data.gemfire.function.config.two.TestOnRegionFunction;
|
||||||
|
import org.springframework.data.gemfire.function.execution.GemfireOnRegionFunctionTemplate;
|
||||||
|
import org.springframework.data.gemfire.function.execution.OnRegionFunctionProxyFactoryBean;
|
||||||
|
import org.springframework.test.context.ContextConfiguration;
|
||||||
|
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||||
|
|
||||||
|
import com.gemstone.gemfire.cache.Region;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author David Turanski
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
@RunWith(SpringJUnit4ClassRunner.class)
|
||||||
|
@ContextConfiguration
|
||||||
|
public class XmlConfiguredFunctionExecutionIntegrationTests {
|
||||||
|
@Autowired
|
||||||
|
ApplicationContext context;
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testProxyFactoryBeanCreated() throws Exception {
|
||||||
|
OnRegionFunctionProxyFactoryBean factoryBean = (OnRegionFunctionProxyFactoryBean)context.getBean("&testFunction");
|
||||||
|
Class<?> serviceInterface = TestUtils.readField("serviceInterface",factoryBean);
|
||||||
|
assertEquals(serviceInterface, TestOnRegionFunction.class);
|
||||||
|
|
||||||
|
Region<?,?> r1 = context.getBean("r1",Region.class);
|
||||||
|
|
||||||
|
GemfireOnRegionFunctionTemplate template = TestUtils.readField("gemfireFunctionOperations",factoryBean);
|
||||||
|
|
||||||
|
assertSame(r1, TestUtils.readField("region",template));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -14,7 +14,6 @@ package org.springframework.data.gemfire.function.config.three;
|
|||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.springframework.data.gemfire.config.GemfireConstants;
|
|
||||||
import org.springframework.data.gemfire.function.config.Filter;
|
import org.springframework.data.gemfire.function.config.Filter;
|
||||||
import org.springframework.data.gemfire.function.config.FunctionId;
|
import org.springframework.data.gemfire.function.config.FunctionId;
|
||||||
import org.springframework.data.gemfire.function.config.OnServer;
|
import org.springframework.data.gemfire.function.config.OnServer;
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import java.util.Set;
|
|||||||
import org.springframework.data.gemfire.function.config.Filter;
|
import org.springframework.data.gemfire.function.config.Filter;
|
||||||
import org.springframework.data.gemfire.function.config.FunctionId;
|
import org.springframework.data.gemfire.function.config.FunctionId;
|
||||||
import org.springframework.data.gemfire.function.config.OnRegion;
|
import org.springframework.data.gemfire.function.config.OnRegion;
|
||||||
import org.springframework.data.gemfire.function.config.OnServer;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author David Turanski
|
* @author David Turanski
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans"
|
||||||
|
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||||
|
xmlns:gfe="http://www.springframework.org/schema/gemfire"
|
||||||
|
xmlns:gfe-data="http://www.springframework.org/schema/data/gemfire"
|
||||||
|
xsi:schemaLocation="http://www.springframework.org/schema/gemfire http://www.springframework.org/schema/gemfire/spring-gemfire-1.3.xsd
|
||||||
|
http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd
|
||||||
|
http://www.springframework.org/schema/data/gemfire http://www.springframework.org/schema/data/gemfire/spring-data-gemfire-1.3.xsd">
|
||||||
|
|
||||||
|
<gfe:cache/>
|
||||||
|
<gfe:local-region id="r1"/>
|
||||||
|
<gfe-data:function-executions base-package="org.springframework.data.gemfire.function.config.two"/>
|
||||||
|
</beans>
|
||||||
Reference in New Issue
Block a user